diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2018-07-03 14:35:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-03 14:35:03 -0700 |
commit | d58df7b53ed79d81eee0340adf95aa364d6a9a6e (patch) | |
tree | 93ccc263ba4702acee53da10ac2ff5ae9145ec07 /spec | |
parent | 7910a42ca5999ae44c5b6b3dc256558b32b42481 (diff) | |
parent | f9e0314265a9f3200ad90eec5c7666ebce9afd6a (diff) | |
download | chef-d58df7b53ed79d81eee0340adf95aa364d6a9a6e.tar.gz |
Merge pull request #7390 from coderanger/yet-more-creds
knife config and a bunch of UX improvements
Diffstat (limited to 'spec')
-rw-r--r-- | spec/integration/knife/config_get_spec.rb | 183 | ||||
-rw-r--r-- | spec/support/shared/integration/knife_support.rb | 8 |
2 files changed, 190 insertions, 1 deletions
diff --git a/spec/integration/knife/config_get_spec.rb b/spec/integration/knife/config_get_spec.rb new file mode 100644 index 0000000000..f34d096051 --- /dev/null +++ b/spec/integration/knife/config_get_spec.rb @@ -0,0 +1,183 @@ +# +# 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", :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", *cmd_args, instance_filter: lambda { |instance| + # Clear the stub set up in KnifeSupport. + allow(File).to receive(:file?).and_call_original + # Lies, damn lies, and config files. We need to allow normal config loading + # behavior to be able to test stuff. + instance.config.delete(:config_file) + $__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 a global knife.rb" do + before { file(".chef/knife.rb", "node_name 'one'\n") } + + it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/.chef/knife.rb$}) } + it { is_expected.to match(/^node_name:\s+one$/) } + end + + context "with a repo knife.rb" do + before { file("repo/.chef/knife.rb", "node_name 'two'\n") } + + it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/repo/.chef/knife.rb$}) } + it { is_expected.to match(/^node_name:\s+two$/) } + end + + context "with both knife.rb" do + before do + file(".chef/knife.rb", "node_name 'one'\n") + file("repo/.chef/knife.rb", "node_name 'two'\n") + end + + it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/repo/.chef/knife.rb$}) } + it { is_expected.to match(/^node_name:\s+two$/) } + end + + context "with a credentials file" do + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/.chef/credentials$}) } + it { is_expected.to match(/^node_name:\s+three$/) } + end + + context "with a credentials file and knife.rb" do + before do + file(".chef/knife.rb", "node_name 'one'\n") + file(".chef/credentials", "[default]\nclient_name = \"three\"\n") + end + + it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/.chef/knife.rb$}) } + it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/.chef/credentials$}) } + it { is_expected.to match(/^node_name:\s+one$/) } + end + + context "with a credentials file and CHEF_HOME" do + before do + file(".chef/credentials", "[default]\nclient_name = \"three\"\n") + file("foo/.chef/credentials", "[default]\nclient_name = \"four\"\n") + ENV["CHEF_HOME"] = path_to("foo") + end + + it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/foo/.chef/credentials$}) } + it { is_expected.to match(/^node_name:\s+four$/) } + end + + context "with a credentials file and KNIFE_HOME" do + before do + file(".chef/credentials", "[default]\nclient_name = \"three\"\n") + file("bar/.chef/credentials", "[default]\nclient_name = \"four\"\n") + ENV["KNIFE_HOME"] = path_to("bar") + end + + it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/bar/.chef/credentials$}) } + it { is_expected.to match(/^node_name:\s+four$/) } + end + + context "with single argument" do + let(:cmd_args) { %w{node_name} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { is_expected.to match(/^node_name:\s+three\Z/) } + end + + context "with two arguments" do + let(:cmd_args) { %w{node_name client_key} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\nclient_key = \"three.pem\"") } + + it { is_expected.to match(/^client_key:\s+\S*\/.chef\/three.pem\nnode_name:\s+three\Z/) } + end + + context "with a dotted argument" do + let(:cmd_args) { %w{knife.ssh_user} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n[default.knife]\nssh_user = \"foo\"\n") } + + it { is_expected.to match(/^knife.ssh_user:\s+foo\Z/) } + end + + context "with regex argument" do + let(:cmd_args) { %w{/name/} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { is_expected.to match(/^node_name:\s+three\Z/) } + end + + context "with --all" do + let(:cmd_args) { %w{-a /key_contents/} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { is_expected.to match(/^client_key_contents:\s+\nvalidation_key_contents:\s+\Z/) } + end + + context "with --raw" do + let(:cmd_args) { %w{-r node_name} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { is_expected.to eq("three\n") } + end + + context "with --format=json" do + let(:cmd_args) { %w{--format=json node_name} } + before { file(".chef/credentials", "[default]\nclient_name = \"three\"\n") } + + it { expect(JSON.parse(subject)).to eq({ "node_name" => "three" }) } + end +end diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb index 5058b7b278..87ce1bc0b0 100644 --- a/spec/support/shared/integration/knife_support.rb +++ b/spec/support/shared/integration/knife_support.rb @@ -24,7 +24,7 @@ require "chef/chef_fs/file_system_cache" module KnifeSupport DEBUG = ENV["DEBUG"] - def knife(*args, input: nil) + def knife(*args, input: nil, instance_filter: nil) # Allow knife('role from file roles/blah.json') rather than requiring the # arguments to be split like knife('role', 'from', 'file', 'roles/blah.json') # If any argument will have actual spaces in it, the long form is required. @@ -88,9 +88,15 @@ module KnifeSupport allow(File).to receive(:file?).and_call_original allow(File).to receive(:file?).with(File.expand_path("~/.chef/credentials")).and_return(false) + # Set a canary that is modified by the default null_config.rb config file. $__KNIFE_INTEGRATION_FAILSAFE_CHECK = "ole" + + # Allow tweaking the knife instance before configuration. + instance_filter.call(instance) if instance_filter + instance.configure_chef + # The canary is incorrect, meaning the normal null_config.rb didn't run. Something is wrong. unless $__KNIFE_INTEGRATION_FAILSAFE_CHECK == "ole ole" raise Exception, "Potential misconfiguration of integration tests detected. Aborting test." end |