summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Kantrowitz <noah@coderanger.net>2018-07-10 18:47:38 -0700
committerNoah Kantrowitz <noah@coderanger.net>2018-07-10 18:47:38 -0700
commitef9b7c95d7e7277dede08b4fd9f2df5af3e76903 (patch)
treef46ff267c1144a16f26df91448905d01e9c5a2af
parentc78512254c655de1d66d0a300b5a7db4cd09adce (diff)
downloadchef-ef9b7c95d7e7277dede08b4fd9f2df5af3e76903.tar.gz
Add two new knife commands for getting and setting the credentials profile name.
Signed-off-by: Noah Kantrowitz <noah@coderanger.net>
-rw-r--r--RELEASE_NOTES.md8
-rw-r--r--lib/chef/knife/config_get_profile.rb37
-rw-r--r--lib/chef/knife/config_use_profile.rb50
-rw-r--r--spec/integration/knife/config_get_profile_spec.rb112
-rw-r--r--spec/integration/knife/config_use_profile_spec.rb100
5 files changed, 307 insertions, 0 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index f1be377c10..d105fa687c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,13 @@
This file holds "in progress" release notes for the current release under development and is intended for consumption by the Chef Documentation team. Please see <https://docs.chef.io/release_notes.html> for the official Chef release notes.
+## New `knife config get-profile` and `knife config use-profile` commands
+
+Two new commands under `knife config` have been added, in addition to the previous
+`knife config get`. `get-profile` will display the active credentials profile
+name. `use-profile` will, conversely, set the default profile name. The default
+profile set via `use-profile` can still be overridden by the `--profile` command
+line option or the `$CHEF_PROFILE` environment variable.
+
# Chef Client Release Notes 14.3:
## New Preview Resources Concept
diff --git a/lib/chef/knife/config_get_profile.rb b/lib/chef/knife/config_get_profile.rb
new file mode 100644
index 0000000000..309b7f81e8
--- /dev/null
+++ b/lib/chef/knife/config_get_profile.rb
@@ -0,0 +1,37 @@
+#
+# Copyright:: Copyright (c) 2018, Noah Kantrowitz
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/knife"
+
+class Chef
+ class Knife
+ class ConfigGetProfile < Knife
+ banner "knife config get-profile"
+
+ # Disable normal config loading since this shouldn't fail if the profile
+ # doesn't exist of the config is otherwise corrupted.
+ def configure_chef
+ apply_computed_config
+ end
+
+ def run
+ ui.msg(self.class.config_loader.credentials_profile(config[:profile]))
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/knife/config_use_profile.rb b/lib/chef/knife/config_use_profile.rb
new file mode 100644
index 0000000000..515c4a5336
--- /dev/null
+++ b/lib/chef/knife/config_use_profile.rb
@@ -0,0 +1,50 @@
+#
+# Copyright:: Copyright (c) 2018, Noah Kantrowitz
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "fileutils"
+
+require "chef/knife"
+
+class Chef
+ class Knife
+ class ConfigUseProfile < Knife
+ banner "knife config use-profile PROFILE"
+
+ # Disable normal config loading since this shouldn't fail if the profile
+ # doesn't exist of the config is otherwise corrupted.
+ def configure_chef
+ apply_computed_config
+ end
+
+ def run
+ context_file = ChefConfig::PathHelper.home(".chef", "context").freeze
+ profile = @name_args[0]&.strip
+ if profile && !profile.empty?
+ # 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
+
+ end
+ end
+end
diff --git a/spec/integration/knife/config_get_profile_spec.rb b/spec/integration/knife/config_get_profile_spec.rb
new file mode 100644
index 0000000000..4566b790ce
--- /dev/null
+++ b/spec/integration/knife/config_get_profile_spec.rb
@@ -0,0 +1,112 @@
+#
+# Copyright 2018, Noah Kantrowitz
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require "support/shared/integration/integration_helper"
+require "support/shared/context/config"
+
+describe "knife config get-profile", :workstation do
+ include IntegrationSupport
+ include KnifeSupport
+
+ include_context "default config options"
+ include_context "with a chef repo"
+
+ let(:cmd_args) { [] }
+
+ subject do
+ cmd = knife("config", "get-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"
+ })
+ cmd.stdout
+ end
+
+ around do |ex|
+ # Store and reset the value of some env vars.
+ old_chef_home = ENV["CHEF_HOME"]
+ old_knife_home = ENV["KNIFE_HOME"]
+ old_home = ENV["HOME"]
+ old_wd = Dir.pwd
+ ChefConfig::PathHelper.per_tool_home_environment = "KNIFE_HOME"
+ # Clear these out because they are cached permanently.
+ ChefConfig::PathHelper.class_exec { remove_class_variable(:@@home_dir) }
+ Chef::Knife::ConfigGet.reset_config_loader!
+ begin
+ ex.run
+ ensure
+ ENV["CHEF_HOME"] = old_chef_home
+ ENV["KNIFE_HOME"] = old_knife_home
+ ENV["HOME"] = old_home
+ Dir.chdir(old_wd)
+ ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd
+ ChefConfig::PathHelper.per_tool_home_environment = nil
+ end
+ end
+
+ before do
+ # Always run from the temp folder. This can't be in the `around` block above
+ # because it has to run after the before set in the "with a chef repo" shared context.
+ directory("repo")
+ Dir.chdir(path_to("repo"))
+ ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd
+ ENV["HOME"] = path_to(".")
+ end
+
+ context "with no configuration" do
+ it { is_expected.to eq "default\n" }
+ end
+
+ context "with --profile" do
+ let(:cmd_args) { %w{--profile production} }
+ it { is_expected.to eq "production\n" }
+ end
+
+ context "with an environment variable" do
+ around do |ex|
+ old_chef_profile = ENV["CHEF_PROFILE"]
+ begin
+ ENV["CHEF_PROFILE"] = "staging"
+ ex.run
+ ensure
+ ENV["CHEF_PROFILE"] = old_chef_profile
+ end
+ end
+
+ it { is_expected.to eq "staging\n" }
+ end
+
+ context "with a context file" do
+ before { file(".chef/context", "development\n") }
+ it { is_expected.to eq "development\n" }
+ end
+
+ context "with a context file under $CHEF_HOME" do
+ before do
+ file("chefhome/.chef/context", "other\n")
+ ENV["CHEF_HOME"] = path_to("chefhome")
+ end
+
+ it { is_expected.to eq "other\n" }
+ end
+
+ context "with a context file under $KNIFE_HOME" do
+ before do
+ file("knifehome/.chef/context", "other\n")
+ ENV["KNIFE_HOME"] = path_to("knifehome")
+ end
+
+ it { is_expected.to eq "other\n" }
+ end
+end
diff --git a/spec/integration/knife/config_use_profile_spec.rb b/spec/integration/knife/config_use_profile_spec.rb
new file mode 100644
index 0000000000..5b224aefe4
--- /dev/null
+++ b/spec/integration/knife/config_use_profile_spec.rb
@@ -0,0 +1,100 @@
+#
+# Copyright 2018, Noah Kantrowitz
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require "support/shared/integration/integration_helper"
+require "support/shared/context/config"
+
+describe "knife config use-profile", :workstation do
+ include IntegrationSupport
+ include KnifeSupport
+
+ include_context "default config options"
+ include_context "with a chef repo"
+
+ let(:cmd_args) { [] }
+
+ let(:knife_use_profile) 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"
+ })
+ end
+
+ subject { knife_use_profile.stdout }
+
+ around do |ex|
+ # Store and reset the value of some env vars.
+ old_chef_home = ENV["CHEF_HOME"]
+ old_knife_home = ENV["KNIFE_HOME"]
+ old_home = ENV["HOME"]
+ old_wd = Dir.pwd
+ ChefConfig::PathHelper.per_tool_home_environment = "KNIFE_HOME"
+ # Clear these out because they are cached permanently.
+ ChefConfig::PathHelper.class_exec { remove_class_variable(:@@home_dir) }
+ Chef::Knife::ConfigGet.reset_config_loader!
+ begin
+ ex.run
+ ensure
+ ENV["CHEF_HOME"] = old_chef_home
+ ENV["KNIFE_HOME"] = old_knife_home
+ ENV["HOME"] = old_home
+ Dir.chdir(old_wd)
+ ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd
+ ChefConfig::PathHelper.per_tool_home_environment = nil
+ end
+ end
+
+ before do
+ # Always run from the temp folder. This can't be in the `around` block above
+ # because it has to run after the before set in the "with a chef repo" shared context.
+ directory("repo")
+ Dir.chdir(path_to("repo"))
+ ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd
+ ENV["HOME"] = path_to(".")
+ end
+
+ context "with no argument" do
+ subject { knife_use_profile.stderr }
+ it { is_expected.to eq "FATAL: You must specify a profile\n" }
+ end
+
+ context "with an argument" do
+ let(:cmd_args) { %w{production} }
+ 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 $CHEF_HOME" do
+ let(:cmd_args) { %w{staging} }
+ before { ENV["CHEF_HOME"] = path_to("chefhome"); file("chefhome/tmp", "") }
+ it do
+ is_expected.to eq "Set default profile to staging\n"
+ expect(File.read(path_to("chefhome/.chef/context"))).to eq "staging\n"
+ expect(File.exist?(path_to(".chef/context"))).to be_falsey
+ end
+ end
+
+ context "with $KNIFE_HOME" do
+ let(:cmd_args) { %w{development} }
+ before { ENV["KNIFE_HOME"] = path_to("knifehome"); file("knifehome/tmp", "") }
+ it do
+ is_expected.to eq "Set default profile to development\n"
+ expect(File.read(path_to("knifehome/.chef/context"))).to eq "development\n"
+ expect(File.exist?(path_to(".chef/context"))).to be_falsey
+ end
+ end
+end