diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2020-04-09 13:28:17 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2020-04-17 10:20:31 -0700 |
commit | d7452360adb80e383b4886246990dbe46d3387c2 (patch) | |
tree | 1d4391bc389a25024fab40ea501745d3e5c8f9dc /spec | |
parent | ac47427ab7090453a680c6c4cf6d32eb85cb270d (diff) | |
download | chef-d7452360adb80e383b4886246990dbe46d3387c2.tar.gz |
Knife bootstrap options cleanup
We have issue that are caused by old code before merging of hash values
were done correctly.
The `config` hash correctly merges all options and should always be
used.
Knife plugins should never touch Chef::Config[:knife] values (either
reading or writing from them).
The `knife_config` should be converted to the `config` hash since it
directly accesses Chef::Config[:knife] values.
The `config_value()` helper should no longer be used. Very clearly most
people started to use that when they should just use the config hash
directly. That was intended to be used only when a knife cli option
was being renamed and the former configuration value needed to be
used as well. It has been cargo culted around as the way to access
config values, and that should really stop.
The DataBagSecretOption mixin has been cleaned up so that the cli
options read+write only to the config[:cl_secret] and
config[:cl_secret_file] values. The config file values go into
config[:secret] and config[:secret_file]. The fact that those are
the merged values in the `config` hash doesn't matter since only
the cli should be writing to the first two and only the config
file should be writing to the latter two. I don't know why it was
made so complicated to begin with, but if there's some hidden
chef-11.early backcompat there, then chef-16 deliberately breaks that.
The use of `locate_config_value` helpers in all knife plugins is also
discouraged (but they all implement those themselves), just use the
config hash, which has the correct hash merge ordering. All of those
need to be deleted.
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'spec')
-rw-r--r-- | spec/functional/knife/ssh_spec.rb | 42 | ||||
-rw-r--r-- | spec/spec_helper.rb | 15 | ||||
-rw-r--r-- | spec/unit/application/client_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/knife/bootstrap/chef_vault_handler_spec.rb | 30 | ||||
-rw-r--r-- | spec/unit/knife/bootstrap/client_builder_spec.rb | 18 | ||||
-rw-r--r-- | spec/unit/knife/bootstrap_spec.rb | 67 | ||||
-rw-r--r-- | spec/unit/knife/core/bootstrap_context_spec.rb | 50 | ||||
-rw-r--r-- | spec/unit/knife/core/windows_bootstrap_context_spec.rb | 70 | ||||
-rw-r--r-- | spec/unit/knife/data_bag_secret_options_spec.rb | 36 | ||||
-rw-r--r-- | spec/unit/knife/ssh_spec.rb | 119 | ||||
-rw-r--r-- | spec/unit/knife_spec.rb | 18 |
11 files changed, 154 insertions, 317 deletions
diff --git a/spec/functional/knife/ssh_spec.rb b/spec/functional/knife/ssh_spec.rb index 4fe919c3a3..4f4290f66d 100644 --- a/spec/functional/knife/ssh_spec.rb +++ b/spec/functional/knife/ssh_spec.rb @@ -50,8 +50,8 @@ describe Chef::Knife::Ssh do describe "identity file" do context "when knife[:ssh_identity_file] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/aws.rsa" + setup_knife(["*:*", "uptime"]) end it "uses the ssh_identity_file" do @@ -62,8 +62,8 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_identity_file] is set and frozen" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/aws.rsa".freeze + setup_knife(["*:*", "uptime"]) end it "uses the ssh_identity_file" do @@ -74,8 +74,8 @@ describe Chef::Knife::Ssh do context "when -i is provided" do before do - setup_knife(["-i ~/.ssh/aws.rsa", "*:*", "uptime"]) Chef::Config[:knife][:ssh_identity_file] = nil + setup_knife(["-i ~/.ssh/aws.rsa", "*:*", "uptime"]) end it "should use the value on the command line" do @@ -85,6 +85,7 @@ describe Chef::Knife::Ssh do it "should override what is set in knife.rb" do Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/other.rsa" + @knife.merge_configs @knife.run expect(@knife.config[:ssh_identity_file]).to eq("~/.ssh/aws.rsa") end @@ -92,8 +93,8 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_identity_file] is not provided]" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_identity_file] = nil + setup_knife(["*:*", "uptime"]) end it "uses the default" do @@ -119,8 +120,8 @@ describe Chef::Knife::Ssh do describe "user" do context "when knife[:ssh_user] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_user] = "ubuntu" + setup_knife(["*:*", "uptime"]) end it "uses the ssh_user" do @@ -131,8 +132,8 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_user] is set and frozen" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_user] = "ubuntu".freeze + setup_knife(["*:*", "uptime"]) end it "uses the ssh_user" do @@ -143,8 +144,8 @@ describe Chef::Knife::Ssh do context "when -x is provided" do before do - setup_knife(["-x ubuntu", "*:*", "uptime"]) Chef::Config[:knife][:ssh_user] = nil + setup_knife(["-x ubuntu", "*:*", "uptime"]) end it "should use the value on the command line" do @@ -154,6 +155,7 @@ describe Chef::Knife::Ssh do it "should override what is set in knife.rb" do Chef::Config[:knife][:ssh_user] = "root" + @knife.merge_configs @knife.run expect(@knife.config[:ssh_user]).to eq("ubuntu") end @@ -161,8 +163,8 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_user] is not provided]" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_user] = nil + setup_knife(["*:*", "uptime"]) end it "uses the default (current user)" do @@ -175,8 +177,8 @@ describe Chef::Knife::Ssh do describe "attribute" do context "when knife[:ssh_attribute] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_attribute] = "ec2.public_hostname" + setup_knife(["*:*", "uptime"]) end it "uses the ssh_attribute" do @@ -187,8 +189,8 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_attribute] is not provided" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_attribute] = nil + setup_knife(["*:*", "uptime"]) end it "uses the default" do @@ -199,8 +201,8 @@ describe Chef::Knife::Ssh do context "when -a ec2.public_public_hostname is provided" do before do - setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"]) Chef::Config[:knife][:ssh_attribute] = nil + setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"]) end it "should use the value on the command line" do @@ -211,6 +213,7 @@ describe Chef::Knife::Ssh do it "should override what is set in knife.rb" do # This is the setting imported from knife.rb Chef::Config[:knife][:ssh_attribute] = "fqdn" + @knife.merge_configs # Then we run knife with the -a flag, which sets the above variable setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"]) @knife.run @@ -222,8 +225,8 @@ describe Chef::Knife::Ssh do describe "prefix" do context "when knife[:prefix_attribute] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:prefix_attribute] = "name" + setup_knife(["*:*", "uptime"]) end it "uses the prefix_attribute" do @@ -234,8 +237,8 @@ describe Chef::Knife::Ssh do context "when knife[:prefix_attribute] is not provided" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:prefix_attribute] = nil + setup_knife(["*:*", "uptime"]) end it "falls back to nil" do @@ -246,8 +249,8 @@ describe Chef::Knife::Ssh do context "when --prefix-attribute ec2.public_public_hostname is provided" do before do - setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"]) Chef::Config[:knife][:prefix_attribute] = nil + setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"]) end it "should use the value on the command line" do @@ -258,6 +261,7 @@ describe Chef::Knife::Ssh do it "should override what is set in knife.rb" do # This is the setting imported from knife.rb Chef::Config[:knife][:prefix_attribute] = "fqdn" + @knife.merge_configs # Then we run knife with the -b flag, which sets the above variable setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"]) @knife.run @@ -269,8 +273,8 @@ describe Chef::Knife::Ssh do describe "gateway" do context "when knife[:ssh_gateway] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_gateway] = "user@ec2.public_hostname" + setup_knife(["*:*", "uptime"]) end it "uses the ssh_gateway" do @@ -282,8 +286,8 @@ describe Chef::Knife::Ssh do context "when -G user@ec2.public_hostname is provided" do before do - setup_knife(["-G user@ec2.public_hostname", "*:*", "uptime"]) Chef::Config[:knife][:ssh_gateway] = nil + setup_knife(["-G user@ec2.public_hostname", "*:*", "uptime"]) end it "uses the ssh_gateway" do @@ -295,9 +299,9 @@ describe Chef::Knife::Ssh do context "when knife[:ssh_gateway_identity] is set" do before do - setup_knife(["*:*", "uptime"]) Chef::Config[:knife][:ssh_gateway] = "user@ec2.public_hostname" Chef::Config[:knife][:ssh_gateway_identity] = "~/.ssh/aws-gateway.rsa" + setup_knife(["*:*", "uptime"]) end it "uses the ssh_gateway_identity file" do @@ -309,9 +313,9 @@ describe Chef::Knife::Ssh do context "when -ssh-gateway-identity is provided and knife[:ssh_gateway] is set" do before do - setup_knife(["--ssh-gateway-identity", "~/.ssh/aws-gateway.rsa", "*:*", "uptime"]) Chef::Config[:knife][:ssh_gateway] = "user@ec2.public_hostname" Chef::Config[:knife][:ssh_gateway_identity] = nil + setup_knife(["--ssh-gateway-identity", "~/.ssh/aws-gateway.rsa", "*:*", "uptime"]) end it "uses the ssh_gateway_identity file" do @@ -323,8 +327,8 @@ describe Chef::Knife::Ssh do context "when the gateway requires a password" do before do - setup_knife(["-G user@ec2.public_hostname", "*:*", "uptime"]) Chef::Config[:knife][:ssh_gateway] = nil + setup_knife(["-G user@ec2.public_hostname", "*:*", "uptime"]) allow(@knife.session).to receive(:via) do |host, user, options| raise Net::SSH::AuthenticationFailed unless options[:password] end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1d85acb4f3..b41e1b3cf3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -114,6 +114,12 @@ resource_priority_map ||= nil provider_handler_map ||= nil resource_handler_map ||= nil +class UnexpectedSystemExit < RuntimeError + def self.from(system_exit) + new(system_exit.message).tap { |e| e.set_backtrace(system_exit.backtrace) } + end +end + RSpec.configure do |config| config.include(Matchers) config.include(MockShellout::RSpec) @@ -291,6 +297,15 @@ RSpec.configure do |config| config.before(:suite) do ARGV.clear end + + # Protect Rspec from accidental exit(0) causing rspec to terminate without error + config.around(:example) do |ex| + begin + ex.run + rescue SystemExit => e + raise UnexpectedSystemExit.from(e) + end + end end require "webrick/utils" diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index 13b98b6434..004debf5ad 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -303,8 +303,12 @@ describe Chef::Application::Client, "reconfigure" do context "when there is no new config" do let(:config_exists) { false } - it "does not updates the config" do + it "does not update the config" do expect(Chef::Config).not_to receive(:from_string) + .with( + "new_config", + File.join("the_path_to_the_repo", ".chef/config.rb") + ) app.reconfigure end diff --git a/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb b/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb index 29eeea62f7..4d36208be0 100644 --- a/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb +++ b/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb @@ -25,12 +25,12 @@ describe Chef::Knife::Bootstrap::ChefVaultHandler do let(:stdin) { StringIO.new } let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) } - let(:knife_config) { {} } + let(:config) { {} } let(:client) { Chef::ApiClient.new } let(:chef_vault_handler) do - chef_vault_handler = Chef::Knife::Bootstrap::ChefVaultHandler.new(knife_config: knife_config, ui: ui) + chef_vault_handler = Chef::Knife::Bootstrap::ChefVaultHandler.new(config: config, ui: ui) chef_vault_handler end @@ -55,28 +55,28 @@ describe Chef::Knife::Bootstrap::ChefVaultHandler do expect(bootstrap_vault_item).to receive(:save).at_least(:once) end - context "from knife_config[:bootstrap_vault_item]" do + context "from config[:bootstrap_vault_item]" do it "sets a single item as a scalar" do - knife_config[:bootstrap_vault_item] = { "vault" => "item1" } + config[:bootstrap_vault_item] = { "vault" => "item1" } expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets a single item as an array" do - knife_config[:bootstrap_vault_item] = { "vault" => [ "item1" ] } + config[:bootstrap_vault_item] = { "vault" => [ "item1" ] } expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets two items as an array" do - knife_config[:bootstrap_vault_item] = { "vault" => %w{item1 item2} } + config[:bootstrap_vault_item] = { "vault" => %w{item1 item2} } expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets two vaults from different hash keys" do - knife_config[:bootstrap_vault_item] = { "vault" => %w{item1 item2}, "vault2" => [ "item3" ] } + config[:bootstrap_vault_item] = { "vault" => %w{item1 item2}, "vault2" => [ "item3" ] } expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault2", "item3").and_return(bootstrap_vault_item) @@ -84,28 +84,28 @@ describe Chef::Knife::Bootstrap::ChefVaultHandler do end end - context "from knife_config[:bootstrap_vault_json]" do + context "from config[:bootstrap_vault_json]" do it "sets a single item as a scalar" do - knife_config[:bootstrap_vault_json] = '{ "vault": "item1" }' + config[:bootstrap_vault_json] = '{ "vault": "item1" }' expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets a single item as an array" do - knife_config[:bootstrap_vault_json] = '{ "vault": [ "item1" ] }' + config[:bootstrap_vault_json] = '{ "vault": [ "item1" ] }' expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets two items as an array" do - knife_config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ] }' + config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ] }' expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) chef_vault_handler.run(client) end it "sets two vaults from different hash keys" do - knife_config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }' + config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }' expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault2", "item3").and_return(bootstrap_vault_item) @@ -113,12 +113,12 @@ describe Chef::Knife::Bootstrap::ChefVaultHandler do end end - context "from knife_config[:bootstrap_vault_file]" do + context "from config[:bootstrap_vault_file]" do def setup_file_contents(json) stringio = StringIO.new(json) - knife_config[:bootstrap_vault_file] = "/foo/bar/baz" - expect(File).to receive(:read).with(knife_config[:bootstrap_vault_file]).and_return(stringio) + config[:bootstrap_vault_file] = "/foo/bar/baz" + expect(File).to receive(:read).with(config[:bootstrap_vault_file]).and_return(stringio) end it "sets a single item as a scalar" do diff --git a/spec/unit/knife/bootstrap/client_builder_spec.rb b/spec/unit/knife/bootstrap/client_builder_spec.rb index 87720091cd..10edd13882 100644 --- a/spec/unit/knife/bootstrap/client_builder_spec.rb +++ b/spec/unit/knife/bootstrap/client_builder_spec.rb @@ -25,7 +25,7 @@ describe Chef::Knife::Bootstrap::ClientBuilder do let(:stdin) { StringIO.new } let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) } - let(:knife_config) { {} } + let(:config) { {} } let(:chef_config) { {} } @@ -34,7 +34,7 @@ describe Chef::Knife::Bootstrap::ClientBuilder do let(:rest) { double("Chef::ServerAPI") } let(:client_builder) do - client_builder = Chef::Knife::Bootstrap::ClientBuilder.new(knife_config: knife_config, chef_config: chef_config, ui: ui) + client_builder = Chef::Knife::Bootstrap::ClientBuilder.new(config: config, chef_config: chef_config, ui: ui) allow(client_builder).to receive(:rest).and_return(rest) allow(client_builder).to receive(:node_name).and_return(node_name) client_builder @@ -160,7 +160,7 @@ describe Chef::Knife::Bootstrap::ClientBuilder do it "adds tags to the node when given" do tag_receiver = [] - knife_config[:tags] = %w{foo bar} + config[:tags] = %w{foo bar} allow(node).to receive(:run_list).with([]) allow(node).to receive(:tags).and_return(tag_receiver) client_builder.run @@ -168,34 +168,34 @@ describe Chef::Knife::Bootstrap::ClientBuilder do end it "builds a node when the run_list is a string" do - knife_config[:run_list] = "role[base],role[app]" + config[:run_list] = "role[base],role[app]" expect(node).to receive(:run_list).with(["role[base]", "role[app]"]) client_builder.run end it "builds a node when the run_list is an Array" do - knife_config[:run_list] = ["role[base]", "role[app]"] + config[:run_list] = ["role[base]", "role[app]"] expect(node).to receive(:run_list).with(["role[base]", "role[app]"]) client_builder.run end it "builds a node with first_boot_attributes if they're given" do - knife_config[:first_boot_attributes] = { baz: :quux } + config[:first_boot_attributes] = { baz: :quux } expect(node).to receive(:normal_attrs=).with({ baz: :quux }) expect(node).to receive(:run_list).with([]) client_builder.run end it "builds a node with an environment if its given" do - knife_config[:environment] = "production" + config[:environment] = "production" expect(node).to receive(:environment).with("production") expect(node).to receive(:run_list).with([]) client_builder.run end it "builds a node with policy_name and policy_group when given" do - knife_config[:policy_name] = "my-app" - knife_config[:policy_group] = "staging" + config[:policy_name] = "my-app" + config[:policy_group] = "staging" expect(node).to receive(:run_list).with([]) expect(node).to receive(:policy_name=).with("my-app") diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index dfe896d3c8..e746c6b936 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -518,6 +518,7 @@ describe Chef::Knife::Bootstrap do before do Chef::Config[:knife][:bootstrap_template] = template_file + knife.merge_configs end let(:rendered_template) do @@ -530,7 +531,6 @@ describe Chef::Knife::Bootstrap do end it "renders 'fips true'" do - Chef::Config[:fips] = true expect(rendered_template).to match("fips") end end @@ -617,6 +617,7 @@ describe Chef::Knife::Bootstrap do allow(knife).to receive(:host_descriptor).and_return host_descriptor if knife_connection_protocol Chef::Config[:knife][:connection_protocol] = knife_connection_protocol + knife.merge_configs end end @@ -827,6 +828,7 @@ describe Chef::Knife::Bootstrap do before do # Set everything to easily identifiable and obviously fake values # to verify that Chef::Config is being sourced instead of knife.config + knife.config = {} Chef::Config[:knife][:max_wait] = 9999 Chef::Config[:knife][:winrm_user] = "winbob" Chef::Config[:knife][:winrm_port] = 9999 @@ -841,20 +843,7 @@ describe Chef::Knife::Bootstrap do Chef::Config[:knife][:winrm_ssl_peer_fingerprint] = "ABCDEF" end - context "and unsupported Chef::Config options are given in Chef::Config, not in CLI" do - before do - Chef::Config[:knife][:connection_password] = "blah" - Chef::Config[:knife][:winrm_password] = "blah" - end - it "does not include the corresponding option in the connection options" do - expect(knife.connection_opts.key?(:password)).to eq false - end - end - context "and no CLI options have been given" do - before do - knife.config = {} - end let(:expected_result) do { logger: Chef::Log, # not configurable @@ -874,6 +863,7 @@ describe Chef::Knife::Bootstrap do end it "generates a config hash using the Chef::Config values" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end @@ -885,7 +875,7 @@ describe Chef::Knife::Bootstrap do logger: Chef::Log, # not configurable ca_trust_path: "no trust", max_wait_until_ready: 9999, - operation_timeout: 60, + operation_timeout: 9999, ssl_peer_fingerprint: "ABCDEF", winrm_transport: "kerberos", winrm_basic_auth_only: true, @@ -908,6 +898,7 @@ describe Chef::Knife::Bootstrap do end it "generates a config hash using the CLI options when available and falling back to Chef::Config values" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -954,6 +945,7 @@ describe Chef::Knife::Bootstrap do } end it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -963,7 +955,6 @@ describe Chef::Knife::Bootstrap do before do # We will use knife's actual config since these tests # have assumptions based on CLI default values - knife.merge_configs end let(:expected_result) do { @@ -977,6 +968,7 @@ describe Chef::Knife::Bootstrap do } end it "populates appropriate defaults" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -990,6 +982,7 @@ describe Chef::Knife::Bootstrap do before do # Set everything to easily identifiable and obviously fake values # to verify that Chef::Config is being sourced instead of knife.config + knife.config = {} Chef::Config[:knife][:max_wait] = 9999 Chef::Config[:knife][:session_timeout] = 9999 Chef::Config[:knife][:ssh_user] = "sshbob" @@ -1002,9 +995,6 @@ describe Chef::Knife::Bootstrap do end context "and no CLI options have been given" do - before do - knife.config = {} - end let(:expected_result) do { logger: Chef::Log, # not configurable @@ -1018,13 +1008,14 @@ describe Chef::Knife::Bootstrap do keys_only: true, key_files: ["/identity.pem", "/gateway.pem"], sudo: false, - verify_host_key: nil, + verify_host_key: "always", port: 9999, non_interactive: true, } end it "generates a correct config hash using the Chef::Config values" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -1038,6 +1029,7 @@ describe Chef::Knife::Bootstrap do Chef::Config[:knife][:ssh_forward_agent] = "blah" end it "does not include the corresponding option in the connection options" do + knife.merge_configs expect(knife.connection_opts.key?(:password)).to eq false expect(knife.connection_opts.key?(:ssh_forward_agent)).to eq false expect(knife.connection_opts.key?(:use_sudo)).to eq false @@ -1047,6 +1039,7 @@ describe Chef::Knife::Bootstrap do context "and some CLI options have been given" do before do + knife.config = {} knife.config[:connection_user] = "sshalice" knife.config[:connection_port] = 12 knife.config[:ssh_port] = "13" # canary to indirectly verify we're not looking for the wrong CLI flag @@ -1072,19 +1065,21 @@ describe Chef::Knife::Bootstrap do keys_only: false, # implied false from config password present key_files: ["/identity.pem", "/gateway.pem"], # Config sudo: true, # ccli - verify_host_key: nil, # Config + verify_host_key: "always", # Config port: 12, # cli non_interactive: true, } end it "generates a config hash using the CLI options when available and falling back to Chef::Config values" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end context "and all CLI options have been given" do before do + knife.config = {} knife.config[:max_wait] = 150 knife.config[:session_timeout] = 120 knife.config[:connection_user] = "sshroot" @@ -1129,6 +1124,7 @@ describe Chef::Knife::Bootstrap do } end it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -1137,7 +1133,7 @@ describe Chef::Knife::Bootstrap do before do # We will use knife's actual config since these tests # have assumptions based on CLI default values - knife.merge_configs + config = {} end let(:expected_result) do @@ -1153,6 +1149,7 @@ describe Chef::Knife::Bootstrap do } end it "populates appropriate defaults" do + knife.merge_configs expect(knife.connection_opts).to match expected_result end end @@ -1169,17 +1166,6 @@ describe Chef::Knife::Bootstrap do allow(knife).to receive(:connection_protocol).and_return connection_protocol end - context "when determining knife config keys for user and port" do - let(:connection_protocol) { "fake" } - it "uses the protocol name to resolve the knife config keys" do - allow(knife).to receive(:config_value).with(:max_wait) - - expect(knife).to receive(:config_value).with(:connection_port, :fake_port) - expect(knife).to receive(:config_value).with(:connection_user, :fake_user) - knife.base_opts - end - end - context "for all protocols" do context "when password is provided" do before do @@ -1940,22 +1926,15 @@ describe Chef::Knife::Bootstrap do Chef::Config[:knife][:test_key_a] = "a from Chef::Config" Chef::Config[:knife][:test_key_c] = "c from Chef::Config" Chef::Config[:knife][:alt_test_key_c] = "alt c from Chef::Config" + knife.merge_configs end - it "returns CLI value when key is only provided by the CLI" do - expect(knife.config_value(:test_key_b)).to eq "b from cli" - end - - it "returns CLI value when key is provided by CLI and Chef::Config" do - expect(knife.config_value(:test_key_a)).to eq "a from cli" - end - - it "returns Chef::Config value whent he key is only provided by Chef::Config" do - expect(knife.config_value(:test_key_c)).to eq "c from Chef::Config" + it "returns the Chef::Config value from the cli when the CLI key is set" do + expect(knife.config_value(:test_key_a, :alt_test_key_c)).to eq "a from cli" end it "returns the Chef::Config value from the alternative key when the CLI key is not set" do - expect(knife.config_value(:test_key_c, :alt_test_key_c)).to eq "alt c from Chef::Config" + expect(knife.config_value(:test_key_d, :alt_test_key_c)).to eq "alt c from Chef::Config" end it "returns the default value when the key is not provided by CLI or Chef::Config" do diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb index c797af38f2..a55047a739 100644 --- a/spec/unit/knife/core/bootstrap_context_spec.rb +++ b/spec/unit/knife/core/bootstrap_context_spec.rb @@ -20,12 +20,6 @@ require "spec_helper" require "chef/knife/core/bootstrap_context" describe Chef::Knife::Core::BootstrapContext do - before do - # This is required because the chef-fips pipeline does - # has a default value of true for fips - Chef::Config[:fips] = false - end - let(:config) { { foo: :bar, color: true } } let(:run_list) { Chef::RunList.new("recipe[tmux]", "role[base]") } let(:chef_config) do @@ -182,34 +176,18 @@ describe Chef::Knife::Core::BootstrapContext do expect(bootstrap_context.config_content).not_to include("ssl_verify_mode") end - describe "when configured in config" do - let(:chef_config) do - { - knife: { ssl_verify_mode: :verify_peer }, - } - end + describe "when configured via the config hash" do + let(:config) { { node_ssl_verify_mode: "none" } } it "uses the config value" do - expect(bootstrap_context.config_content).to include("ssl_verify_mode :verify_peer") - end - - describe "when configured via CLI" do - let(:config) { { node_ssl_verify_mode: "none" } } - - it "uses CLI value" do - expect(bootstrap_context.config_content).to include("ssl_verify_mode :verify_none") - end + expect(bootstrap_context.config_content).to include("ssl_verify_mode :verify_none") end end end describe "fips mode" do before do - Chef::Config[:fips] = true - end - - after do - Chef::Config.reset! + chef_config[:fips] = true end it "sets fips mode in the client.rb" do @@ -222,23 +200,11 @@ describe Chef::Knife::Core::BootstrapContext do expect(bootstrap_context.config_content).not_to include("verify_api_cert") end - describe "when configured in config" do - let(:chef_config) do - { - knife: { verify_api_cert: :false }, - } - end - - it "uses the config value" do - expect(bootstrap_context.config_content).to include("verify_api_cert false") - end - - describe "when configured via CLI" do - let(:config) { { node_verify_api_cert: true } } + describe "when configured via the config hash" do + let(:config) { { node_verify_api_cert: true } } - it "uses CLI value" do - expect(bootstrap_context.config_content).to include("verify_api_cert true") - end + it "uses config value" do + expect(bootstrap_context.config_content).to include("verify_api_cert true") end end end diff --git a/spec/unit/knife/core/windows_bootstrap_context_spec.rb b/spec/unit/knife/core/windows_bootstrap_context_spec.rb index 14ca563a58..656b05b905 100644 --- a/spec/unit/knife/core/windows_bootstrap_context_spec.rb +++ b/spec/unit/knife/core/windows_bootstrap_context_spec.rb @@ -20,19 +20,14 @@ require "spec_helper" require "chef/knife/core/windows_bootstrap_context" describe Chef::Knife::Core::WindowsBootstrapContext do let(:config) { {} } - let(:bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new(config, nil, Chef::Config, nil) } + let(:chef_config) { Chef::Config.save } # "dup" to a hash + let(:bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new(config, nil, chef_config, nil) } describe "fips" do - before do - Chef::Config[:fips] = fips_mode - end - - after do - Chef::Config.reset! - end - context "when fips is set" do - let(:fips_mode) { true } + before do + chef_config[:fips] = true + end it "sets fips mode in the client.rb" do expect(bootstrap_context.config_content).to match(/fips true/) @@ -40,7 +35,9 @@ describe Chef::Knife::Core::WindowsBootstrapContext do end context "when fips is not set" do - let(:fips_mode) { false } + before do + chef_config[:fips] = false + end it "sets fips mode in the client.rb" do expect(bootstrap_context.config_content).not_to match(/fips true/) @@ -223,55 +220,4 @@ describe Chef::Knife::Core::WindowsBootstrapContext do end end end - - describe "bootstrap_install_command for bootstrap through WinRM" do - context "when bootstrap_install_command option is passed on CLI" do - let(:bootstrap) { Chef::Knife::Bootstrap.new(["--bootstrap-install-command", "chef-client"]) } - before do - bootstrap.config[:bootstrap_install_command] = "chef-client" - end - - it "sets the bootstrap_install_command option under Chef::Config::Knife object" do - expect(Chef::Config[:knife][:bootstrap_install_command]).to eq("chef-client") - end - - after do - bootstrap.config.delete(:bootstrap_install_command) - Chef::Config[:knife].delete(:bootstrap_install_command) - end - end - - context "when bootstrap_install_command option is not passed on CLI" do - let(:bootstrap) { Chef::Knife::Bootstrap.new([]) } - it "does not set the bootstrap_install_command option under Chef::Config::Knife object" do - expect(Chef::Config[:knife][:bootstrap_install_command]). to eq(nil) - end - end - end - - describe "bootstrap_install_command for bootstrap through SSH" do - context "when bootstrap_install_command option is passed on CLI" do - let(:bootstrap) { Chef::Knife::Bootstrap.new(["--bootstrap-install-command", "chef-client"]) } - before do - bootstrap.config[:bootstrap_install_command] = "chef-client" - end - - it "sets the bootstrap_install_command option under Chef::Config::Knife object" do - expect(Chef::Config[:knife][:bootstrap_install_command]).to eq("chef-client") - end - - after do - bootstrap.config.delete(:bootstrap_install_command) - Chef::Config[:knife].delete(:bootstrap_install_command) - end - end - - context "when bootstrap_install_command option is not passed on CLI" do - let(:bootstrap) { Chef::Knife::Bootstrap.new([]) } - it "does not set the bootstrap_install_command option under Chef::Config::Knife object" do - expect(Chef::Config[:knife][:bootstrap_install_command]). to eq(nil) - end - end - end - end diff --git a/spec/unit/knife/data_bag_secret_options_spec.rb b/spec/unit/knife/data_bag_secret_options_spec.rb index 2b9425999c..e8f99c3f79 100644 --- a/spec/unit/knife/data_bag_secret_options_spec.rb +++ b/spec/unit/knife/data_bag_secret_options_spec.rb @@ -50,8 +50,8 @@ describe Chef::Knife::DataBagSecretOptions do describe "#validate_secrets" do it "throws an error when provided with both --secret and --secret-file on the CL" do - Chef::Config[:knife][:cl_secret_file] = secret_file.path - Chef::Config[:knife][:cl_secret] = secret + example_db.config[:cl_secret_file] = secret_file.path + example_db.config[:cl_secret] = secret expect(example_db).to receive(:exit).with(1) expect(example_db.ui).to receive(:fatal).with("Please specify only one of --secret, --secret-file") @@ -61,6 +61,7 @@ describe Chef::Knife::DataBagSecretOptions do it "throws an error when provided with `secret` and `secret_file` in knife.rb" do Chef::Config[:knife][:secret_file] = secret_file.path Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db).to receive(:exit).with(1) expect(example_db.ui).to receive(:fatal).with("Please specify only one of 'secret' or 'secret_file' in your config file") @@ -72,14 +73,16 @@ describe Chef::Knife::DataBagSecretOptions do describe "#read_secret" do it "returns the secret first" do - Chef::Config[:knife][:cl_secret] = secret - expect(example_db).to receive(:config).and_return({ secret: secret }) + example_db.config[:cl_secret] = secret + Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db.read_secret).to eq(secret) end it "returns the secret_file only if secret does not exist" do - Chef::Config[:knife][:cl_secret_file] = secret_file.path - expect(example_db).to receive(:config).and_return({ secret_file: secret_file.path }) + example_db.config[:cl_secret_file] = secret_file.path + Chef::Config[:knife][:secret_file] = secret_file.path + example_db.merge_configs expect(Chef::EncryptedDataBagItem).to receive(:load_secret).with(secret_file.path).and_return("secret file contents") expect(example_db.read_secret).to eq("secret file contents") end @@ -87,11 +90,13 @@ describe Chef::Knife::DataBagSecretOptions do it "returns the secret from the knife.rb config" do Chef::Config[:knife][:secret_file] = secret_file.path Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db.read_secret).to eq(secret) end it "returns the secret_file from the knife.rb config only if the secret does not exist" do Chef::Config[:knife][:secret_file] = secret_file.path + example_db.merge_configs expect(Chef::EncryptedDataBagItem).to receive(:load_secret).with(secret_file.path).and_return("secret file contents") expect(example_db.read_secret).to eq("secret file contents") end @@ -101,58 +106,61 @@ describe Chef::Knife::DataBagSecretOptions do describe "#encryption_secret_provided?" do it "returns true if the secret is passed on the CL" do - Chef::Config[:knife][:cl_secret] = secret + example_db.config[:cl_secret] = secret expect(example_db.encryption_secret_provided?).to eq(true) end it "returns true if the secret_file is passed on the CL" do - Chef::Config[:knife][:cl_secret_file] = secret_file.path + example_db.config[:cl_secret_file] = secret_file.path expect(example_db.encryption_secret_provided?).to eq(true) end it "returns true if --encrypt is passed on the CL and :secret is in config" do - expect(example_db).to receive(:config).and_return({ encrypt: true }) + example_db.config[:encrypt] = true Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db.encryption_secret_provided?).to eq(true) end it "returns true if --encrypt is passed on the CL and :secret_file is in config" do - expect(example_db).to receive(:config).and_return({ encrypt: true }) + example_db.config[:encrypt] = true Chef::Config[:knife][:secret_file] = secret_file.path + example_db.merge_configs expect(example_db.encryption_secret_provided?).to eq(true) end it "throws an error if --encrypt is passed and there is not :secret or :secret_file in the config" do - expect(example_db).to receive(:config).and_return({ encrypt: true }) + example_db.config[:encrypt] = true expect(example_db).to receive(:exit).with(1) expect(example_db.ui).to receive(:fatal).with("No secret or secret_file specified in config, unable to encrypt item.") example_db.encryption_secret_provided? end it "returns false if no secret is passed" do - expect(example_db).to receive(:config).and_return({}) expect(example_db.encryption_secret_provided?).to eq(false) end it "returns false if --encrypt is not provided and :secret is in the config" do - expect(example_db).to receive(:config).and_return({}) Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db.encryption_secret_provided?).to eq(false) end it "returns false if --encrypt is not provided and :secret_file is in the config" do - expect(example_db).to receive(:config).and_return({}) Chef::Config[:knife][:secret_file] = secret_file.path + example_db.merge_configs expect(example_db.encryption_secret_provided?).to eq(false) end it "returns true if --encrypt is not provided, :secret is in the config and need_encrypt_flag is false" do Chef::Config[:knife][:secret] = secret + example_db.merge_configs expect(example_db.encryption_secret_provided_ignore_encrypt_flag?).to eq(true) end it "returns true if --encrypt is not provided, :secret_file is in the config and need_encrypt_flag is false" do Chef::Config[:knife][:secret_file] = secret_file.path + example_db.merge_configs expect(example_db.encryption_secret_provided_ignore_encrypt_flag?).to eq(true) end diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb index 470868d479..72111eed3d 100644 --- a/spec/unit/knife/ssh_spec.rb +++ b/spec/unit/knife/ssh_spec.rb @@ -253,15 +253,19 @@ describe Chef::Knife::Ssh do expect(@knife.session.servers[0].options[:timeout]).to eq(120) end - it "uses the timeout from Chef Config" do - Chef::Config[:knife][:ssh_timeout] = 5 - @knife.config[:ssh_timeout] = nil + it "uses the timeout from the CLI" do + @knife.config = {} + Chef::Config[:knife][:ssh_timeout] = nil + @knife.config[:ssh_timeout] = 5 @knife.session_from_list([["the.b.org", nil, nil]]) + @knife.merge_configs expect(@knife.session.servers[0].options[:timeout]).to eq(5) end it "uses the timeout from knife config" do - @knife.config[:ssh_timeout] = 6 + @knife.config = {} + Chef::Config[:knife][:ssh_timeout] = 6 + @knife.merge_configs @knife.session_from_list([["the.b.org", nil, nil]]) expect(@knife.session.servers[0].options[:timeout]).to eq(6) end @@ -396,111 +400,4 @@ describe Chef::Knife::Ssh do end end end - - describe "#configure_password" do - before do - @knife.config.delete(:ssh_password_ng) - @knife.config.delete(:ssh_password) - end - - context "when setting ssh_password_ng from knife ssh" do - # in this case ssh_password_ng exists, but ssh_password does not - it "should prompt for a password when ssh_passsword_ng is nil" do - @knife.config[:ssh_password_ng] = nil - expect(@knife).to receive(:get_password).and_return("mysekretpassw0rd") - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - - it "should set ssh_password to false if ssh_password_ng is false" do - @knife.config[:ssh_password_ng] = false - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to be_falsey - end - - it "should set ssh_password to ssh_password_ng if we set a password" do - @knife.config[:ssh_password_ng] = "mysekretpassw0rd" - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - end - - context "when setting ssh_password from knife bootstrap / knife * server create" do - # in this case ssh_password exists, but ssh_password_ng does not - it "should set ssh_password to nil when ssh_password is nil" do - @knife.config[:ssh_password] = nil - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to be_nil - end - - it "should set ssh_password to false when ssh_password is false" do - @knife.config[:ssh_password] = false - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to be_falsey - end - - it "should set ssh_password to ssh_password if we set a password" do - @knife.config[:ssh_password] = "mysekretpassw0rd" - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - end - context "when setting ssh_password in the config variable" do - before(:each) do - Chef::Config[:knife][:ssh_password] = "my_knife_passw0rd" - end - context "when setting ssh_password_ng from knife ssh" do - # in this case ssh_password_ng exists, but ssh_password does not - it "should prompt for a password when ssh_passsword_ng is nil" do - @knife.config[:ssh_password_ng] = nil - expect(@knife).to receive(:get_password).and_return("mysekretpassw0rd") - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - - it "should set ssh_password to the configured knife.rb value if ssh_password_ng is false" do - @knife.config[:ssh_password_ng] = false - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("my_knife_passw0rd") - end - - it "should set ssh_password to ssh_password_ng if we set a password" do - @knife.config[:ssh_password_ng] = "mysekretpassw0rd" - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - end - - context "when setting ssh_password from knife bootstrap / knife * server create" do - # in this case ssh_password exists, but ssh_password_ng does not - it "should set ssh_password to the configured knife.rb value when ssh_password is nil" do - @knife.config[:ssh_password] = nil - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("my_knife_passw0rd") - end - - it "should set ssh_password to the configured knife.rb value when ssh_password is false" do - @knife.config[:ssh_password] = false - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("my_knife_passw0rd") - end - - it "should set ssh_password to ssh_password if we set a password" do - @knife.config[:ssh_password] = "mysekretpassw0rd" - expect(@knife).not_to receive(:get_password) - @knife.configure_password - expect(@knife.config[:ssh_password]).to eq("mysekretpassw0rd") - end - end - end - end end diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb index b73a46397f..88f36a3973 100644 --- a/spec/unit/knife_spec.rb +++ b/spec/unit/knife_spec.rb @@ -353,6 +353,24 @@ describe Chef::Knife do expect(knife_command.config_source(:listen)).to eq(:cli) end + it "merges Chef::Config[:knife] values into the config hash even if they have no cli keys" do + Chef::Config[:knife][:opt_with_no_cli_key] = "from-knife-config" + knife_command = KnifeSpecs::TestYourself.new([]) # empty argv + knife_command.configure_chef + expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-config") + expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config) + end + + it "merges Chef::Config[:knife] default values into the config hash even if they have no cli keys" do + Chef::Config.config_context :knife do + default :opt_with_no_cli_key, "from-knife-default" + end + knife_command = KnifeSpecs::TestYourself.new([]) # empty argv + knife_command.configure_chef + expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-default") + expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config_default) + end + context "verbosity is one" do let(:fake_config) { "/does/not/exist/knife.rb" } |