summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2020-04-09 13:28:17 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2020-04-17 10:20:31 -0700
commitd7452360adb80e383b4886246990dbe46d3387c2 (patch)
tree1d4391bc389a25024fab40ea501745d3e5c8f9dc
parentac47427ab7090453a680c6c4cf6d32eb85cb270d (diff)
downloadchef-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>
-rw-r--r--lib/chef/deprecated.rb4
-rw-r--r--lib/chef/knife.rb46
-rw-r--r--lib/chef/knife/bootstrap.rb179
-rw-r--r--lib/chef/knife/bootstrap/chef_vault_handler.rb20
-rw-r--r--lib/chef/knife/bootstrap/client_builder.rb42
-rw-r--r--lib/chef/knife/bootstrap/templates/chef-full.erb22
-rw-r--r--lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb16
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb122
-rw-r--r--lib/chef/knife/core/generic_presenter.rb7
-rw-r--r--lib/chef/knife/core/windows_bootstrap_context.rb84
-rw-r--r--lib/chef/knife/data_bag_secret_options.rb51
-rw-r--r--lib/chef/knife/ssh.rb43
-rw-r--r--lib/chef/knife/status.rb2
-rw-r--r--lib/chef/knife/supermarket_download.rb3
-rw-r--r--lib/chef/knife/supermarket_install.rb3
-rw-r--r--lib/chef/knife/supermarket_list.rb3
-rw-r--r--lib/chef/knife/supermarket_search.rb3
-rw-r--r--lib/chef/knife/supermarket_share.rb3
-rw-r--r--lib/chef/knife/supermarket_show.rb3
-rw-r--r--lib/chef/knife/supermarket_unshare.rb3
-rw-r--r--spec/functional/knife/ssh_spec.rb42
-rw-r--r--spec/spec_helper.rb15
-rw-r--r--spec/unit/application/client_spec.rb6
-rw-r--r--spec/unit/knife/bootstrap/chef_vault_handler_spec.rb30
-rw-r--r--spec/unit/knife/bootstrap/client_builder_spec.rb18
-rw-r--r--spec/unit/knife/bootstrap_spec.rb67
-rw-r--r--spec/unit/knife/core/bootstrap_context_spec.rb50
-rw-r--r--spec/unit/knife/core/windows_bootstrap_context_spec.rb70
-rw-r--r--spec/unit/knife/data_bag_secret_options_spec.rb36
-rw-r--r--spec/unit/knife/ssh_spec.rb119
-rw-r--r--spec/unit/knife_spec.rb18
31 files changed, 467 insertions, 663 deletions
diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb
index 7062e27aab..ecc589d263 100644
--- a/lib/chef/deprecated.rb
+++ b/lib/chef/deprecated.rb
@@ -233,6 +233,10 @@ class Chef
target 28
end
+ class KnifeBootstrapApis < Base
+ target 29
+ end
+
class Generic < Base
def url
"https://docs.chef.io/chef_deprecations_client/"
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 1bf02df0df..bdab024579 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -343,31 +343,35 @@ class Chef
exit(1)
end
- # keys from mixlib-cli options
- def cli_keys
- self.class.options.keys
+ # This is all set and default mixlib-config values. We only need the default
+ # values here (the set values are explicitly mixed in again later), but there is
+ # no mixlib-config API to get a Hash back with only the default values.
+ #
+ # Assumption: since config_file_defaults is the lowest precedence it doesn't matter
+ # that we include the set values here, but this is a hack and makes the name of the
+ # method a lie. FIXME: make the name not a lie by adding an API to mixlib-config.
+ #
+ # @api private
+ #
+ def config_file_defaults
+ Chef::Config[:knife].save(true) # this is like "dup" to a (real) Hash, and includes default values (and user set values)
end
- # extracts the settings from the Chef::Config[:knife] sub-hash that correspond
- # to knife cli options -- in preparation for merging config values with cli values
+ # This is only the user-set mixlib-config values. We do not include the defaults
+ # here so that the config defaults do not override the cli defaults.
+ #
+ # @api private
#
- # NOTE: due to weirdness in mixlib-config #has_key? is only true if the value has
- # been set by the user -- the Chef::Config defaults return #has_key?() of false and
- # this code DEPENDS on that functionality since applying the default values in
- # Chef::Config[:knife] would break the defaults in the cli that we would otherwise
- # overwrite.
def config_file_settings
- cli_keys.each_with_object({}) do |key, memo|
- if Chef::Config[:knife].key?(key)
- memo[key] = Chef::Config[:knife][key]
- end
- end
+ Chef::Config[:knife].save(false) # this is like "dup" to a (real) Hash, and does not include default values (just user set values)
end
# config is merged in this order (inverse of precedence)
- # default_config - mixlib-cli defaults (accessor from the mixin)
- # config_file_settings - Chef::Config[:knife] sub-hash
- # config - mixlib-cli settings (accessor from the mixin)
+ # config_file_defaults - Chef::Config[:knife] defaults from chef-config (XXX: this also includes the settings, but they get overwritten)
+ # default_config - mixlib-cli defaults (accessor from mixlib-cli)
+ # config_file_settings - Chef::Config[:knife] user settings from the client.rb file
+ # config - mixlib-cli settings (accessor from mixlib-cli)
+ #
def merge_configs
# Update our original_config - if someone has created a knife command
# instance directly, they are likely ot have set cmd.config values directly
@@ -375,7 +379,7 @@ class Chef
@original_config = config.dup
# other code may have a handle to the config object, so use Hash#replace to deliberately
# update-in-place.
- config.replace(default_config.merge(config_file_settings).merge(config))
+ config.replace(config_file_defaults.merge(default_config).merge(config_file_settings).merge(config))
end
#
@@ -385,8 +389,9 @@ class Chef
# @return [Symbol,NilClass] return the source of the config key,
# one of:
# - :cli - this was explicitly provided on the CLI
- # - :config - this came from Chef::Config[:knife]
+ # - :config - this came from Chef::Config[:knife] explicitly being set
# - :cli_default - came from a declared CLI `option`'s `default` value.
+ # - :config_default - this came from Chef::Config[:knife]'s defaults
# - nil - if the key could not be found in any source.
# This can happen when it is invalid, or has been
# set directly into #config without then calling #merge_config
@@ -394,6 +399,7 @@ class Chef
return :cli if @original_config.include? key
return :config if config_file_settings.key? key
return :cli_default if default_config.include? key
+ return :config_default if config_file_defaults.key? key # must come after :config check
nil
end
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index 3128dd4af9..bb6c5871c6 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -86,7 +86,6 @@ class Chef
short: "-w AUTH-METHOD",
long: "--winrm-auth-method AUTH-METHOD",
description: "The WinRM authentication method to use.",
- proc: Proc.new { |protocol| Chef::Config[:knife][:winrm_auth_method] = protocol },
in: WINRM_AUTH_PROTOCOL_LIST
option :winrm_basic_auth_only,
@@ -99,32 +98,27 @@ class Chef
# option :kerberos_keytab_file,
# :short => "-T KEYTAB_FILE",
# :long => "--keytab-file KEYTAB_FILE",
- # :description => "The Kerberos keytab file used for authentication",
- # :proc => Proc.new { |keytab| Chef::Config[:knife][:kerberos_keytab_file] = keytab }
+ # :description => "The Kerberos keytab file used for authentication"
option :kerberos_realm,
short: "-R KERBEROS_REALM",
long: "--kerberos-realm KERBEROS_REALM",
- description: "The Kerberos realm used for authentication.",
- proc: Proc.new { |protocol| Chef::Config[:knife][:kerberos_realm] = protocol }
+ description: "The Kerberos realm used for authentication."
option :kerberos_service,
short: "-S KERBEROS_SERVICE",
long: "--kerberos-service KERBEROS_SERVICE",
- description: "The Kerberos service used for authentication.",
- proc: Proc.new { |protocol| Chef::Config[:knife][:kerberos_service] = protocol }
+ description: "The Kerberos service used for authentication."
## SSH Authentication
option :ssh_gateway,
short: "-G GATEWAY",
long: "--ssh-gateway GATEWAY",
- description: "The SSH gateway.",
- proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
+ description: "The SSH gateway."
option :ssh_gateway_identity,
long: "--ssh-gateway-identity SSH_GATEWAY_IDENTITY",
- description: "The SSH identity file used for gateway authentication.",
- proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key }
+ description: "The SSH identity file used for gateway authentication."
option :ssh_forward_agent,
short: "-A",
@@ -140,7 +134,8 @@ class Chef
option :ssh_verify_host_key,
long: "--ssh-verify-host-key VALUE",
description: "Verify host key. Default is 'always'.",
- in: %w{always accept_new accept_new_or_local_tunnel never}
+ in: %w{always accept_new accept_new_or_local_tunnel never},
+ default: "always"
#
# bootstrap options
@@ -160,8 +155,7 @@ class Chef
# client.rb content via chef-full/bootstrap_context
option :bootstrap_proxy,
long: "--bootstrap-proxy PROXY_URL",
- description: "The proxy server for the node being bootstrapped.",
- proc: Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
+ description: "The proxy server for the node being bootstrapped."
# client.rb content via bootstrap_context
option :bootstrap_proxy_user,
@@ -176,8 +170,7 @@ class Chef
# client.rb content via bootstrap_context
option :bootstrap_no_proxy,
long: "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]",
- description: "Do not proxy locations for the node being bootstrapped",
- proc: Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
+ description: "Do not proxy locations for the node being bootstrapped"
# client.rb content via bootstrap_context
option :bootstrap_template,
@@ -270,21 +263,16 @@ class Chef
proc: lambda { |o| Chef::JSONCompat.parse(File.read(o)) },
default: nil
- # Note that several of the below options are used by bootstrap template,
- # but only from the passed-in knife config; it does not use the
- # config from the CLI for those values. We cannot always used the merged
- # config, because in some cases the knife keys thIn those cases, the option
- # will have a proc that assigns the value into Chef::Config[:knife]
-
# bootstrap template
# Create ohai hints in /etc/chef/ohai/hints, fname=hintname, content=value
- option :hint,
+ option :hints,
long: "--hint HINT_NAME[=HINT_FILE]",
description: "Specify an Ohai hint to be set on the bootstrap target. Use multiple --hint options to specify multiple hints.",
- proc: Proc.new { |h|
- Chef::Config[:knife][:hints] ||= {}
- name, path = h.split("=")
- Chef::Config[:knife][:hints][name] = path ? Chef::JSONCompat.parse(::File.read(path)) : {}
+ proc: Proc.new { |hint, accumulator|
+ accumulator ||= {}
+ name, path = hint.split("=", 2)
+ accumulator[name] = path ? Chef::JSONCompat.parse(::File.read(path)) : {}
+ accumulator
}
# bootstrap override: url of a an installer shell script touse in place of omnitruck
@@ -292,8 +280,7 @@ class Chef
# the provided options to knife bootstrap, so we set the Chef::Config option here.
option :bootstrap_url,
long: "--bootstrap-url URL",
- description: "URL to a custom installation script.",
- proc: Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u }
+ description: "URL to a custom installation script."
option :bootstrap_product,
long: "--bootstrap-product PRODUCT",
@@ -309,26 +296,22 @@ class Chef
# bootstrap override: Do this instead of our own setup.sh from omnitruck. Causes bootstrap_url to be ignored.
option :bootstrap_install_command,
long: "--bootstrap-install-command COMMANDS",
- description: "Custom command to install #{Chef::Dist::PRODUCT}.",
- proc: Proc.new { |ic| Chef::Config[:knife][:bootstrap_install_command] = ic }
+ description: "Custom command to install #{Chef::Dist::PRODUCT}."
# bootstrap template: Run this command first in the bootstrap script
option :bootstrap_preinstall_command,
long: "--bootstrap-preinstall-command COMMANDS",
- description: "Custom commands to run before installing #{Chef::Dist::PRODUCT}.",
- proc: Proc.new { |preic| Chef::Config[:knife][:bootstrap_preinstall_command] = preic }
+ description: "Custom commands to run before installing #{Chef::Dist::PRODUCT}."
# bootstrap template
option :bootstrap_wget_options,
long: "--bootstrap-wget-options OPTIONS",
- description: "Add options to wget when installing #{Chef::Dist::PRODUCT}.",
- proc: Proc.new { |wo| Chef::Config[:knife][:bootstrap_wget_options] = wo }
+ description: "Add options to wget when installing #{Chef::Dist::PRODUCT}."
# bootstrap template
option :bootstrap_curl_options,
long: "--bootstrap-curl-options OPTIONS",
- description: "Add options to curl when install #{Chef::Dist::PRODUCT}.",
- proc: Proc.new { |co| Chef::Config[:knife][:bootstrap_curl_options] = co }
+ description: "Add options to curl when install #{Chef::Dist::PRODUCT}."
# chef_vault_handler
option :bootstrap_vault_file,
@@ -344,12 +327,12 @@ class Chef
option :bootstrap_vault_item,
long: "--bootstrap-vault-item VAULT_ITEM",
description: 'A single vault and item to update as "vault:item".',
- proc: Proc.new { |i|
+ proc: Proc.new { |i, accumulator|
(vault, item) = i.split(/:/)
- Chef::Config[:knife][:bootstrap_vault_item] ||= {}
- Chef::Config[:knife][:bootstrap_vault_item][vault] ||= []
- Chef::Config[:knife][:bootstrap_vault_item][vault].push(item)
- Chef::Config[:knife][:bootstrap_vault_item]
+ accumulator ||= {}
+ accumulator[vault] ||= []
+ accumulator[vault].push(item)
+ accumulator
}
# Deprecated options. These must be declared after
@@ -434,14 +417,14 @@ class Chef
def client_builder
@client_builder ||= Chef::Knife::Bootstrap::ClientBuilder.new(
chef_config: Chef::Config,
- knife_config: config,
+ config: config,
ui: ui
)
end
def chef_vault_handler
@chef_vault_handler ||= Chef::Knife::Bootstrap::ChefVaultHandler.new(
- knife_config: config,
+ config: config,
ui: ui
)
end
@@ -686,9 +669,8 @@ class Chef
return @connection_protocol if @connection_protocol
from_url = host_descriptor =~ %r{^(.*)://} ? $1 : nil
- from_cli = config[:connection_protocol]
- from_knife = Chef::Config[:knife][:connection_protocol]
- @connection_protocol = from_url || from_cli || from_knife || "ssh"
+ from_knife = config[:connection_protocol]
+ @connection_protocol = from_url || from_knife || "ssh"
end
def do_connect(conn_options)
@@ -724,6 +706,10 @@ class Chef
true
end
+ def winrm_auth_method
+ config_value(:winrm_auth_method, :winrm_authentication_protocol, "negotiate")
+ end
+
# Fail if using plaintext auth without ssl because
# this can expose keys in plaintext on the wire.
# TODO test for this method
@@ -732,8 +718,8 @@ class Chef
return true unless winrm?
if Chef::Config[:validation_key] && !File.exist?(File.expand_path(Chef::Config[:validation_key]))
- if config_value(:winrm_auth_method) == "plaintext" &&
- config_value(:winrm_ssl) != true
+ if winrm_auth_method == "plaintext" &&
+ config[:winrm_ssl] != true
ui.error <<~EOM
Validatorless bootstrap over unsecure winrm channels could expose your
key to network sniffing.
@@ -857,9 +843,9 @@ class Chef
# Reference:
# https://github.com/chef/knife-windows/blob/92d151298142be4a4750c5b54bb264f8d5b81b8a/lib/chef/knife/winrm_knife_base.rb#L271-L273
# TODO Seems like we should also do a similar warning if ssh_verify_host == false
- if config_value(:ca_trust_file).nil? &&
- config_value(:winrm_no_verify_cert) &&
- config_value(:winrm_ssl_peer_fingerprint).nil?
+ if config[:ca_trust_file].nil? &&
+ config[:winrm_no_verify_cert] &&
+ config[:winrm_ssl_peer_fingerprint].nil?
ui.warn <<~WARN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
SSL validation of HTTPS requests for the WinRM transport is disabled.
@@ -905,16 +891,13 @@ class Chef
# Common configuration for all protocols
def base_opts
- port = config_value(:connection_port,
- knife_key_for_protocol(connection_protocol, :port))
- user = config_value(:connection_user,
- knife_key_for_protocol(connection_protocol, :user))
+ port = config_for_protocol(:port)
+ user = config_for_protocol(:user)
{}.tap do |opts|
opts[:logger] = Chef::Log
- # We do not store password in Chef::Config, so only use CLI `config` here
opts[:password] = config[:connection_password] if config.key?(:connection_password)
opts[:user] = user if user
- opts[:max_wait_until_ready] = config_value(:max_wait).to_f unless config_value(:max_wait).nil?
+ opts[:max_wait_until_ready] = config[:max_wait].to_f unless config[:max_wait].nil?
# TODO - when would we need to provide rdp_port vs port? Or are they not mutually exclusive?
opts[:port] = port if port
end
@@ -922,7 +905,7 @@ class Chef
def host_verify_opts
if winrm?
- { self_signed: config_value(:winrm_no_verify_cert) === true }
+ { self_signed: config[:winrm_no_verify_cert] === true }
elsif ssh?
# Fall back to the old knife config key name for back compat.
{ verify_host_key: config_value(:ssh_verify_host_key, :host_key_verify, "always") }
@@ -936,7 +919,7 @@ class Chef
return opts if winrm?
opts[:non_interactive] = true # Prevent password prompts from underlying net/ssh
- opts[:forward_agent] = (config_value(:ssh_forward_agent) === true)
+ opts[:forward_agent] = (config[:ssh_forward_agent] === true)
opts[:connection_timeout] = session_timeout
opts
end
@@ -945,7 +928,7 @@ class Chef
opts = {}
return opts if winrm?
- identity_file = config_value(:ssh_identity_file)
+ identity_file = config[:ssh_identity_file]
if identity_file
opts[:key_files] = [identity_file]
# We only set keys_only based on the explicit ssh_identity_file;
@@ -965,7 +948,7 @@ class Chef
opts[:keys_only] = false
end
- gateway_identity_file = config_value(:ssh_gateway) ? config_value(:ssh_gateway_identity) : nil
+ gateway_identity_file = config[:ssh_gateway] ? config[:ssh_gateway_identity] : nil
unless gateway_identity_file.nil?
opts[:key_files] << gateway_identity_file
end
@@ -975,8 +958,8 @@ class Chef
def gateway_opts
opts = {}
- if config_value(:ssh_gateway)
- split = config_value(:ssh_gateway).split("@", 2)
+ if config[:ssh_gateway]
+ split = config[:ssh_gateway].split("@", 2)
if split.length == 1
gw_host = split[0]
else
@@ -1022,21 +1005,20 @@ class Chef
def winrm_opts
return {} unless winrm?
- auth_method = config_value(:winrm_auth_method, :winrm_auth_method, "negotiate")
opts = {
- winrm_transport: auth_method, # winrm gem and train calls auth method 'transport'
- winrm_basic_auth_only: config_value(:winrm_basic_auth_only) || false,
- ssl: config_value(:winrm_ssl) === true,
- ssl_peer_fingerprint: config_value(:winrm_ssl_peer_fingerprint),
+ winrm_transport: winrm_auth_method, # winrm gem and train calls auth method 'transport'
+ winrm_basic_auth_only: config[:winrm_basic_auth_only] || false,
+ ssl: config[:winrm_ssl] === true,
+ ssl_peer_fingerprint: config[:winrm_ssl_peer_fingerprint],
}
- if auth_method == "kerberos"
- opts[:kerberos_service] = config_value(:kerberos_service) if config_value(:kerberos_service)
- opts[:kerberos_realm] = config_value(:kerberos_realm) if config_value(:kerberos_service)
+ if winrm_auth_method == "kerberos"
+ opts[:kerberos_service] = config[:kerberos_service] if config[:kerberos_service]
+ opts[:kerberos_realm] = config[:kerberos_realm] if config[:kerberos_service]
end
- if config_value(:ca_trust_file)
- opts[:ca_trust_path] = config_value(:ca_trust_file)
+ if config[:ca_trust_file]
+ opts[:ca_trust_path] = config[:ca_trust_file]
end
opts[:operation_timeout] = session_timeout
@@ -1061,24 +1043,26 @@ class Chef
}
end
- # Looks up configuration entries, first in the class member
- # `config` which contains options populated from CLI flags.
- # If the entry is not found there, Chef::Config[:knife][KEY]
- # is checked.
+ # This is for deprecating config options. The fallback_key can be used
+ # to pull an old knife config option out of the config file when the
+ # cli value has been renamed. This is different from the deprecated
+ # cli values, since these are for config options that have no corresponding
+ # cli value.
#
- # knife_config_key should be specified if the knife config lookup
- # key is different from the CLI flag lookup key.
+ # DO NOT USE - this whole API is considered deprecated
#
- def config_value(key, knife_config_key = nil, default = nil)
- if config.key? key
+ # @api deprecated
+ #
+ def config_value(key, fallback_key = nil, default = nil)
+ Chef.deprecated(:knife_bootstrap_apis, "Use of config_value without a fallback_key is deprecated. Knife plugin authors should access the config hash directly, which does correct merging of cli and config options.") if fallback_key.nil?
+ if config.key?(key)
+ # the first key is the primary key so we check the merged hash first
config[key]
+ elsif config.key?(fallback_key)
+ # we get the old config option here (the deprecated cli option shouldn't exist)
+ config[fallback_key]
else
- lookup_key = knife_config_key || key
- if Chef::Config[:knife].key?(lookup_key) || config.key?(lookup_key)
- Chef::Config[:knife][lookup_key] || config[lookup_key]
- else
- default
- end
+ default
end
end
@@ -1099,6 +1083,8 @@ class Chef
end
end
+ private
+
# To avoid cluttering the CLI options, some flags (such as port and user)
# are shared between protocols. However, there is still a need to allow the operator
# to specify defaults separately, since they may not be the same values for different
@@ -1107,11 +1093,20 @@ class Chef
# These keys are available in Chef::Config, and are prefixed with the protocol name.
# For example, :user CLI option will map to :winrm_user and :ssh_user Chef::Config keys,
# based on the connection protocol in use.
- def knife_key_for_protocol(protocol, option)
- "#{connection_protocol}_#{option}".to_sym
+
+ # @api private
+ def config_for_protocol(option)
+ if option == :port
+ config[:connection_port] || config[knife_key_for_protocol(option)]
+ else
+ config[:connection_user] || config[knife_key_for_protocol(option)]
+ end
end
- private
+ # @api private
+ def knife_key_for_protocol(option)
+ "#{connection_protocol}_#{option}".to_sym
+ end
# True if policy_name and run_list are both given
def policyfile_and_run_list_given?
@@ -1134,7 +1129,7 @@ class Chef
# session_timeout option has a default that may not arrive, particularly if
# we're being invoked from a plugin that doesn't merge_config.
def session_timeout
- timeout = config_value(:session_timeout)
+ timeout = config[:session_timeout]
return options[:session_timeout][:default] if timeout.nil?
timeout.to_i
diff --git a/lib/chef/knife/bootstrap/chef_vault_handler.rb b/lib/chef/knife/bootstrap/chef_vault_handler.rb
index 7007e1403b..00f902d728 100644
--- a/lib/chef/knife/bootstrap/chef_vault_handler.rb
+++ b/lib/chef/knife/bootstrap/chef_vault_handler.rb
@@ -21,7 +21,7 @@ class Chef
class ChefVaultHandler
# @return [Hash] knife merged config, typically @config
- attr_accessor :knife_config
+ attr_accessor :config
# @return [Chef::Knife::UI] ui object for output
attr_accessor :ui
@@ -29,11 +29,15 @@ class Chef
# @return [Chef::ApiClient] vault client
attr_reader :client
- # @param knife_config [Hash] knife merged config, typically @config
+ # @param config [Hash] knife merged config, typically @config
# @param ui [Chef::Knife::UI] ui object for output
- def initialize(knife_config: {}, ui: nil)
- @knife_config = knife_config
- @ui = ui
+ def initialize(config: {}, knife_config: nil, ui: nil)
+ @config = config
+ unless knife_config.nil?
+ @config = knife_config
+ Chef.deprecated(:knife_bootstrap_apis, "The knife_config option to the Bootstrap::ClientBuilder object is deprecated and has been renamed to just 'config'")
+ end
+ @ui = ui
end
# Updates the chef vault items for the newly created client.
@@ -85,17 +89,17 @@ class Chef
# @return [String] string with serialized JSON representing the chef vault items
def bootstrap_vault_json
- knife_config[:bootstrap_vault_json]
+ config[:bootstrap_vault_json]
end
# @return [String] JSON text in a file representing the chef vault items
def bootstrap_vault_file
- knife_config[:bootstrap_vault_file]
+ config[:bootstrap_vault_file]
end
# @return [Hash] Ruby object representing the chef vault items to create
def bootstrap_vault_item
- knife_config[:bootstrap_vault_item]
+ config[:bootstrap_vault_item]
end
# Helper to return a ruby object represeting all the data bags and items
diff --git a/lib/chef/knife/bootstrap/client_builder.rb b/lib/chef/knife/bootstrap/client_builder.rb
index d557cc1feb..b2c07e8019 100644
--- a/lib/chef/knife/bootstrap/client_builder.rb
+++ b/lib/chef/knife/bootstrap/client_builder.rb
@@ -28,7 +28,7 @@ class Chef
class ClientBuilder
# @return [Hash] knife merged config, typically @config
- attr_accessor :knife_config
+ attr_accessor :config
# @return [Hash] chef config object
attr_accessor :chef_config
# @return [Chef::Knife::UI] ui object for output
@@ -36,13 +36,17 @@ class Chef
# @return [Chef::ApiClient] client saved on run
attr_reader :client
- # @param knife_config [Hash] Hash of knife config settings
+ # @param config [Hash] Hash of knife config settings
# @param chef_config [Hash] Hash of chef config settings
# @param ui [Chef::Knife::UI] UI object for output
- def initialize(knife_config: {}, chef_config: {}, ui: nil)
- @knife_config = knife_config
- @chef_config = chef_config
- @ui = ui
+ def initialize(config: {}, knife_config: nil, chef_config: {}, ui: nil)
+ @config = config
+ unless knife_config.nil?
+ @config = knife_config
+ Chef.deprecated(:knife_bootstrap_apis, "The knife_config option to the Bootstrap::ClientBuilder object is deprecated and has been renamed to just 'config'")
+ end
+ @chef_config = chef_config
+ @ui = ui
end
# Main entry. Prompt the user to clean up any old client or node objects. Then create
@@ -77,34 +81,34 @@ class Chef
private
- # @return [String] node name from the knife_config
+ # @return [String] node name from the config
def node_name
- knife_config[:chef_node_name]
+ config[:chef_node_name]
end
- # @return [String] enviroment from the knife_config
+ # @return [String] enviroment from the config
def environment
- knife_config[:environment]
+ config[:environment]
end
- # @return [String] run_list from the knife_config
+ # @return [String] run_list from the config
def run_list
- knife_config[:run_list]
+ config[:run_list]
end
- # @return [String] policy_name from the knife_config
+ # @return [String] policy_name from the config
def policy_name
- knife_config[:policy_name]
+ config[:policy_name]
end
- # @return [String] policy_group from the knife_config
+ # @return [String] policy_group from the config
def policy_group
- knife_config[:policy_group]
+ config[:policy_group]
end
- # @return [Hash,Array] Object representation of json first-boot attributes from the knife_config
+ # @return [Hash,Array] Object representation of json first-boot attributes from the config
def first_boot_attributes
- knife_config[:first_boot_attributes]
+ config[:first_boot_attributes]
end
# @return [String] chef server url from the Chef::Config
@@ -154,7 +158,7 @@ class Chef
node.environment(environment) if environment
node.policy_name = policy_name if policy_name
node.policy_group = policy_group if policy_group
- (knife_config[:tags] || []).each do |tag|
+ (config[:tags] || []).each do |tag|
node.tags << tag
end
node
diff --git a/lib/chef/knife/bootstrap/templates/chef-full.erb b/lib/chef/knife/bootstrap/templates/chef-full.erb
index 263203ca76..b4f75720ac 100644
--- a/lib/chef/knife/bootstrap/templates/chef-full.erb
+++ b/lib/chef/knife/bootstrap/templates/chef-full.erb
@@ -1,5 +1,5 @@
-<%= "https_proxy=\"#{knife_config[:bootstrap_proxy]}\" export https_proxy" if knife_config[:bootstrap_proxy] %>
-<%= "no_proxy=\"#{knife_config[:bootstrap_no_proxy]}\" export no_proxy" if knife_config[:bootstrap_no_proxy] %>
+<%= "https_proxy=\"#{@config[:bootstrap_proxy]}\" export https_proxy" if @config[:bootstrap_proxy] %>
+<%= "no_proxy=\"#{@config[:bootstrap_no_proxy]}\" export no_proxy" if @config[:bootstrap_no_proxy] %>
if test "x$TMPDIR" = "x"; then
tmp="/tmp"
@@ -37,7 +37,7 @@ capture_tmp_stderr() {
# do_wget URL FILENAME
do_wget() {
echo "trying wget..."
- wget <%= "--proxy=on " if knife_config[:bootstrap_proxy] %> <%= knife_config[:bootstrap_wget_options] %> -O "$2" "$1" 2>$tmp_dir/stderr
+ wget <%= "--proxy=on " if @config[:bootstrap_proxy] %> <%= @config[:bootstrap_wget_options] %> -O "$2" "$1" 2>$tmp_dir/stderr
rc=$?
# check for 404
grep "ERROR 404" $tmp_dir/stderr 2>&1 >/dev/null
@@ -57,7 +57,7 @@ do_wget() {
# do_curl URL FILENAME
do_curl() {
echo "trying curl..."
- curl -sL <%= "--proxy \"#{knife_config[:bootstrap_proxy]}\" " if knife_config[:bootstrap_proxy] %> <%= knife_config[:bootstrap_curl_options] %> -D $tmp_dir/stderr -o "$2" "$1" 2>$tmp_dir/stderr
+ curl -sL <%= "--proxy \"#{@config[:bootstrap_proxy]}\" " if @config[:bootstrap_proxy] %> <%= @config[:bootstrap_curl_options] %> -D $tmp_dir/stderr -o "$2" "$1" 2>$tmp_dir/stderr
rc=$?
# check for 404
grep "404 Not Found" $tmp_dir/stderr 2>&1 >/dev/null
@@ -164,14 +164,14 @@ do_download() {
<%# Run any custom commands before installing chef-client -%>
<%# Ex. wait for cloud-init to complete -%>
-<% if knife_config[:bootstrap_preinstall_command] %>
- <%= knife_config[:bootstrap_preinstall_command] %>
+<% if @config[:bootstrap_preinstall_command] %>
+ <%= @config[:bootstrap_preinstall_command] %>
<% end %>
-<% if knife_config[:bootstrap_install_command] %>
- <%= knife_config[:bootstrap_install_command] %>
+<% if @config[:bootstrap_install_command] %>
+ <%= @config[:bootstrap_install_command] %>
<% else %>
- install_sh="<%= knife_config[:bootstrap_url] ? knife_config[:bootstrap_url] : "https://omnitruck.chef.io/chef/install.sh" %>"
+ install_sh="<%= @config[:bootstrap_url] ? @config[:bootstrap_url] : "https://omnitruck.chef.io/chef/install.sh" %>"
if test -f /usr/bin/<%= Chef::Dist::CLIENT %>; then
echo "-----> Existing <%= Chef::Dist::PRODUCT %> installation detected"
else
@@ -214,10 +214,10 @@ mkdir -p <%= ChefConfig::Config.etc_chef_dir(false) %>/trusted_certs
<% end -%>
<%# Generate Ohai Hints -%>
-<% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
+<% unless @config[:hints].nil? || @config[:hints].empty? -%>
mkdir -p <%= ChefConfig::Config.etc_chef_dir(false) %>/ohai/hints
-<% @chef_config[:knife][:hints].each do |name, hash| -%>
+<% @config[:hints].each do |name, hash| -%>
cat > <%= ChefConfig::Config.etc_chef_dir(false) %>/ohai/hints/<%= name %>.json <<'EOP'
<%= Chef::JSONCompat.to_json(hash) %>
EOP
diff --git a/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb b/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb
index b4da79e453..0b444e718c 100644
--- a/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb
+++ b/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb
@@ -21,7 +21,7 @@
@rem the line is read. See help for the /E switch from cmd.exe /? .
@setlocal ENABLEDELAYEDEXPANSION
-<%= "SETX HTTP_PROXY \"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] %>
+<%= "SETX HTTP_PROXY \"#{@config[:bootstrap_proxy]}\"" if @config[:bootstrap_proxy] %>
@set BOOTSTRAP_DIRECTORY=<%= bootstrap_directory %>
@echo Checking for existing directory "%BOOTSTRAP_DIRECTORY%"...
@@ -92,10 +92,10 @@ goto architecture_select
goto Version10.0
:architecture_select
-<% if knife_config[:architecture] %>
- @set MACHINE_ARCH=<%= knife_config[:architecture] %>
+<% if @config[:architecture] %>
+ @set MACHINE_ARCH=<%= @config[:architecture] %>
- <% if knife_config[:architecture] == "x86_64" %>
+ <% if @config[:architecture] == "x86_64" %>
IF "%PROCESSOR_ARCHITECTURE%"=="x86" IF not defined PROCESSOR_ARCHITEW6432 (
echo You specified bootstrap_architecture as x86_64 but the target machine is i386. A 64 bit program cannot run on a 32 bit machine. > "&2"
echo Exiting without bootstrapping. > "&2"
@@ -121,8 +121,8 @@ If !ERRORLEVEL!==0 (
:install
@rem If user has provided the custom installation command, execute it
-<% if @chef_config[:knife][:bootstrap_install_command] %>
- <%= @chef_config[:knife][:bootstrap_install_command] %>
+<% if @config[:bootstrap_install_command] %>
+ <%= @config[:bootstrap_install_command] %>
<% else %>
@rem Install Chef using the MSI installer
@@ -244,12 +244,12 @@ echo Validation key written.
<% end -%>
<%# Generate Ohai Hints -%>
-<% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
+<% unless @config[:hints].nil? || @config[:hints].empty? -%>
@if NOT EXIST <%= bootstrap_directory %>\ohai\hints (
mkdir <%= bootstrap_directory %>\ohai\hints
)
-<% @chef_config[:knife][:hints].each do |name, hash| -%>
+<% @config[:hints].each do |name, hash| -%>
> <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
<%= escape_and_echo(hash.to_json) %>
)
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index 85693d7bbd..7d99ea0d96 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -33,6 +33,8 @@ class Chef
class BootstrapContext
attr_accessor :client_pem
+ attr_accessor :config
+ attr_accessor :chef_config
def initialize(config, run_list, chef_config, secret = nil)
@config = config
@@ -42,13 +44,13 @@ class Chef
end
def bootstrap_environment
- @config[:environment]
+ config[:environment]
end
def validation_key
- if @chef_config[:validation_key] &&
- File.exist?(File.expand_path(@chef_config[:validation_key]))
- IO.read(File.expand_path(@chef_config[:validation_key]))
+ if chef_config[:validation_key] &&
+ File.exist?(File.expand_path(chef_config[:validation_key]))
+ IO.read(File.expand_path(chef_config[:validation_key]))
else
false
end
@@ -69,18 +71,18 @@ class Chef
end
def get_log_location
- if !(@chef_config[:config_log_location].class == IO ) && (@chef_config[:config_log_location].nil? || @chef_config[:config_log_location].to_s.empty?)
+ if !(chef_config[:config_log_location].class == IO ) && (chef_config[:config_log_location].nil? || chef_config[:config_log_location].to_s.empty?)
"STDOUT"
- elsif @chef_config[:config_log_location].equal?(:win_evt)
+ elsif chef_config[:config_log_location].equal?(:win_evt)
raise "The value :win_evt is not supported for config_log_location on Linux Platforms \n"
- elsif @chef_config[:config_log_location].equal?(:syslog)
+ elsif chef_config[:config_log_location].equal?(:syslog)
":syslog"
- elsif @chef_config[:config_log_location].equal?(STDOUT)
+ elsif chef_config[:config_log_location].equal?(STDOUT)
"STDOUT"
- elsif @chef_config[:config_log_location].equal?(STDERR)
+ elsif chef_config[:config_log_location].equal?(STDERR)
"STDERR"
- elsif @chef_config[:config_log_location]
- %Q{"#{@chef_config[:config_log_location]}"}
+ elsif chef_config[:config_log_location]
+ %Q{"#{chef_config[:config_log_location]}"}
else
"STDOUT"
end
@@ -88,43 +90,43 @@ class Chef
def config_content
client_rb = <<~CONFIG
- chef_server_url "#{@chef_config[:chef_server_url]}"
- validation_client_name "#{@chef_config[:validation_client_name]}"
+ chef_server_url "#{chef_config[:chef_server_url]}"
+ validation_client_name "#{chef_config[:validation_client_name]}"
CONFIG
- unless @chef_config[:chef_license].nil?
- client_rb << "chef_license \"#{@chef_config[:chef_license]}\"\n"
+ unless chef_config[:chef_license].nil?
+ client_rb << "chef_license \"#{chef_config[:chef_license]}\"\n"
end
- unless @chef_config[:config_log_level].nil? || @chef_config[:config_log_level].empty?
- client_rb << %Q{log_level :#{@chef_config[:config_log_level]}\n}
+ unless chef_config[:config_log_level].nil? || chef_config[:config_log_level].empty?
+ client_rb << %Q{log_level :#{chef_config[:config_log_level]}\n}
end
client_rb << "log_location #{get_log_location}\n"
- if @config[:chef_node_name]
- client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
+ if config[:chef_node_name]
+ client_rb << %Q{node_name "#{config[:chef_node_name]}"\n}
else
client_rb << "# Using default node name (fqdn)\n"
end
# We configure :verify_api_cert only when it's overridden on the CLI
# or when specified in the knife config.
- if !@config[:node_verify_api_cert].nil? || knife_config.key?(:verify_api_cert)
- value = @config[:node_verify_api_cert].nil? ? knife_config[:verify_api_cert] : @config[:node_verify_api_cert]
+ if !config[:node_verify_api_cert].nil? || config.key?(:verify_api_cert)
+ value = config[:node_verify_api_cert].nil? ? config[:verify_api_cert] : config[:node_verify_api_cert]
client_rb << %Q{verify_api_cert #{value}\n}
end
# We configure :ssl_verify_mode only when it's overridden on the CLI
# or when specified in the knife config.
- if @config[:node_ssl_verify_mode] || knife_config.key?(:ssl_verify_mode)
- value = case @config[:node_ssl_verify_mode]
+ if config[:node_ssl_verify_mode] || config.key?(:ssl_verify_mode)
+ value = case config[:node_ssl_verify_mode]
when "peer"
:verify_peer
when "none"
:verify_none
when nil
- knife_config[:ssl_verify_mode]
+ config[:ssl_verify_mode]
else
nil
end
@@ -134,27 +136,27 @@ class Chef
end
end
- if @config[:ssl_verify_mode]
- client_rb << %Q{ssl_verify_mode :#{knife_config[:ssl_verify_mode]}\n}
+ if config[:ssl_verify_mode]
+ client_rb << %Q{ssl_verify_mode :#{config[:ssl_verify_mode]}\n}
end
- if knife_config[:bootstrap_proxy]
- client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
- client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
+ if config[:bootstrap_proxy]
+ client_rb << %Q{http_proxy "#{config[:bootstrap_proxy]}"\n}
+ client_rb << %Q{https_proxy "#{config[:bootstrap_proxy]}"\n}
end
- if knife_config[:bootstrap_proxy_user]
- client_rb << %Q{http_proxy_user "#{knife_config[:bootstrap_proxy_user]}"\n}
- client_rb << %Q{https_proxy_user "#{knife_config[:bootstrap_proxy_user]}"\n}
+ if config[:bootstrap_proxy_user]
+ client_rb << %Q{http_proxy_user "#{config[:bootstrap_proxy_user]}"\n}
+ client_rb << %Q{https_proxy_user "#{config[:bootstrap_proxy_user]}"\n}
end
- if knife_config[:bootstrap_proxy_pass]
- client_rb << %Q{http_proxy_pass "#{knife_config[:bootstrap_proxy_pass]}"\n}
- client_rb << %Q{https_proxy_pass "#{knife_config[:bootstrap_proxy_pass]}"\n}
+ if config[:bootstrap_proxy_pass]
+ client_rb << %Q{http_proxy_pass "#{config[:bootstrap_proxy_pass]}"\n}
+ client_rb << %Q{https_proxy_pass "#{config[:bootstrap_proxy_pass]}"\n}
end
- if knife_config[:bootstrap_no_proxy]
- client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n}
+ if config[:bootstrap_no_proxy]
+ client_rb << %Q{no_proxy "#{config[:bootstrap_no_proxy]}"\n}
end
if encrypted_data_bag_secret
@@ -165,16 +167,16 @@ class Chef
client_rb << %Q{trusted_certs_dir "/etc/chef/trusted_certs"\n}
end
- if Chef::Config[:fips]
+ if chef_config[:fips]
client_rb << "fips true\n"
end
- unless @chef_config[:file_cache_path].nil?
- client_rb << "file_cache_path \"#{@chef_config[:file_cache_path]}\"\n"
+ unless chef_config[:file_cache_path].nil?
+ client_rb << "file_cache_path \"#{chef_config[:file_cache_path]}\"\n"
end
- unless @chef_config[:file_backup_path].nil?
- client_rb << "file_backup_path \"#{@chef_config[:file_backup_path]}\"\n"
+ unless chef_config[:file_backup_path].nil?
+ client_rb << "file_backup_path \"#{chef_config[:file_backup_path]}\"\n"
end
client_rb
@@ -182,32 +184,26 @@ class Chef
def start_chef
# If the user doesn't have a client path configure, let bash use the PATH for what it was designed for
- client_path = @chef_config[:chef_client_path] || "#{Chef::Dist::CLIENT}"
+ client_path = chef_config[:chef_client_path] || "#{Chef::Dist::CLIENT}"
s = "#{client_path} -j /etc/chef/first-boot.json"
- if @config[:verbosity] && @config[:verbosity] >= 3
+ if config[:verbosity] && config[:verbosity] >= 3
s << " -l trace"
- elsif @config[:verbosity] && @config[:verbosity] >= 2
+ elsif config[:verbosity] && config[:verbosity] >= 2
s << " -l debug"
end
s << " -E #{bootstrap_environment}" unless bootstrap_environment.nil?
- s << " --no-color" unless @config[:color]
+ s << " --no-color" unless config[:color]
s
end
- # XXX: this reads values only out of the config file and is NOT merged with the CLI options, and it is most likely
- # a bug to be using this accessor and we should be using config and not knife_config.
- def knife_config
- @chef_config.key?(:knife) ? @chef_config[:knife] : {}
- end
-
#
# Returns the version of Chef to install (as recognized by the Omnitruck API)
#
# @return [String] download version string
def version_to_install
- return @config[:bootstrap_version] if @config[:bootstrap_version]
+ return config[:bootstrap_version] if config[:bootstrap_version]
- if @config[:channel] == "stable"
+ if config[:channel] == "stable"
Chef::VERSION.split(".").first
else
"latest"
@@ -215,15 +211,15 @@ class Chef
end
def first_boot
- (@config[:first_boot_attributes] = Mash.new(@config[:first_boot_attributes]) || Mash.new).tap do |attributes|
- if @config[:policy_name] && @config[:policy_group]
- attributes[:policy_name] = @config[:policy_name]
- attributes[:policy_group] = @config[:policy_group]
+ (config[:first_boot_attributes] = Mash.new(config[:first_boot_attributes]) || Mash.new).tap do |attributes|
+ if config[:policy_name] && config[:policy_group]
+ attributes[:policy_name] = config[:policy_name]
+ attributes[:policy_group] = config[:policy_group]
else
attributes[:run_list] = @run_list
end
attributes.delete(:run_list) if attributes[:policy_name] && !attributes[:policy_name].empty?
- attributes.merge!(tags: @config[:tags]) if @config[:tags] && !@config[:tags].empty?
+ attributes.merge!(tags: config[:tags]) if config[:tags] && !config[:tags].empty?
end
end
@@ -233,8 +229,8 @@ class Chef
# This string should contain both the commands necessary to both create the files, as well as their content
def trusted_certs_content
content = ""
- if @chef_config[:trusted_certs_dir]
- Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(@chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
+ if chef_config[:trusted_certs_dir]
+ Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
content << "cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'\n" +
IO.read(File.expand_path(cert)) + "\nEOP\n"
end
@@ -244,8 +240,8 @@ class Chef
def client_d_content
content = ""
- if @chef_config[:client_d_dir] && File.exist?(@chef_config[:client_d_dir])
- root = Pathname(@chef_config[:client_d_dir])
+ if chef_config[:client_d_dir] && File.exist?(chef_config[:client_d_dir])
+ root = Pathname(chef_config[:client_d_dir])
root.find do |f|
relative = f.relative_path_from(root)
if f != root
diff --git a/lib/chef/knife/core/generic_presenter.rb b/lib/chef/knife/core/generic_presenter.rb
index 02d3a55595..bca5b5bfaf 100644
--- a/lib/chef/knife/core/generic_presenter.rb
+++ b/lib/chef/knife/core/generic_presenter.rb
@@ -37,9 +37,10 @@ class Chef
short: "-a ATTR1 [-a ATTR2]",
long: "--attribute ATTR1 [--attribute ATTR2] ",
description: "Show one or more attributes",
- proc: Proc.new { |a|
- Chef::Config[:knife][:attribute] ||= []
- Chef::Config[:knife][:attribute].push(a)
+ proc: Proc.new { |arg, accumulator|
+ accumulator ||= []
+ accumulator << arg
+ accumulator
}
end
end
diff --git a/lib/chef/knife/core/windows_bootstrap_context.rb b/lib/chef/knife/core/windows_bootstrap_context.rb
index 5c4df857ae..e05409f6c4 100644
--- a/lib/chef/knife/core/windows_bootstrap_context.rb
+++ b/lib/chef/knife/core/windows_bootstrap_context.rb
@@ -30,6 +30,8 @@ class Chef
# * @run_list - the run list for the node to boostrap
#
class WindowsBootstrapContext < BootstrapContext
+ attr_accessor :config
+ attr_accessor :chef_config
def initialize(config, run_list, chef_config, secret = nil)
@config = config
@@ -40,15 +42,15 @@ class Chef
end
def validation_key
- if File.exist?(File.expand_path(@chef_config[:validation_key]))
- IO.read(File.expand_path(@chef_config[:validation_key]))
+ if File.exist?(File.expand_path(chef_config[:validation_key]))
+ IO.read(File.expand_path(chef_config[:validation_key]))
else
false
end
end
def secret
- escape_and_echo(@config[:secret])
+ escape_and_echo(config[:secret])
end
def trusted_certs_script
@@ -57,25 +59,25 @@ class Chef
def config_content
client_rb = <<~CONFIG
- chef_server_url "#{@chef_config[:chef_server_url]}"
- validation_client_name "#{@chef_config[:validation_client_name]}"
+ chef_server_url "#{chef_config[:chef_server_url]}"
+ validation_client_name "#{chef_config[:validation_client_name]}"
file_cache_path "#{ChefConfig::Config.var_chef_dir(true)}/cache"
file_backup_path "#{ChefConfig::Config.var_chef_dir(true)}/backup"
cache_options ({:path => "#{ChefConfig::Config.etc_chef_dir(true)}/cache/checksums", :skip_expires => true})
CONFIG
- unless @chef_config[:chef_license].nil?
- client_rb << "chef_license \"#{@chef_config[:chef_license]}\"\n"
+ unless chef_config[:chef_license].nil?
+ client_rb << "chef_license \"#{chef_config[:chef_license]}\"\n"
end
- if @config[:chef_node_name]
- client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
+ if config[:chef_node_name]
+ client_rb << %Q{node_name "#{config[:chef_node_name]}"\n}
else
client_rb << "# Using default node name (fqdn)\n"
end
- if @chef_config[:config_log_level]
- client_rb << %Q{log_level :#{@chef_config[:config_log_level]}\n}
+ if chef_config[:config_log_level]
+ client_rb << %Q{log_level :#{chef_config[:config_log_level]}\n}
else
client_rb << "log_level :auto\n"
end
@@ -84,21 +86,21 @@ class Chef
# We configure :verify_api_cert only when it's overridden on the CLI
# or when specified in the knife config.
- if !@config[:node_verify_api_cert].nil? || knife_config.key?(:verify_api_cert)
- value = @config[:node_verify_api_cert].nil? ? knife_config[:verify_api_cert] : @config[:node_verify_api_cert]
+ if !config[:node_verify_api_cert].nil? || config.key?(:verify_api_cert)
+ value = config[:node_verify_api_cert].nil? ? config[:verify_api_cert] : config[:node_verify_api_cert]
client_rb << %Q{verify_api_cert #{value}\n}
end
# We configure :ssl_verify_mode only when it's overridden on the CLI
# or when specified in the knife config.
- if @config[:node_ssl_verify_mode] || knife_config.key?(:ssl_verify_mode)
- value = case @config[:node_ssl_verify_mode]
+ if config[:node_ssl_verify_mode] || config.key?(:ssl_verify_mode)
+ value = case config[:node_ssl_verify_mode]
when "peer"
:verify_peer
when "none"
:verify_none
when nil
- knife_config[:ssl_verify_mode]
+ config[:ssl_verify_mode]
else
nil
end
@@ -108,22 +110,22 @@ class Chef
end
end
- if @config[:ssl_verify_mode]
- client_rb << %Q{ssl_verify_mode :#{knife_config[:ssl_verify_mode]}\n}
+ if config[:ssl_verify_mode]
+ client_rb << %Q{ssl_verify_mode :#{config[:ssl_verify_mode]}\n}
end
- if knife_config[:bootstrap_proxy]
+ if config[:bootstrap_proxy]
client_rb << "\n"
- client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
- client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
- client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n} if knife_config[:bootstrap_no_proxy]
+ client_rb << %Q{http_proxy "#{config[:bootstrap_proxy]}"\n}
+ client_rb << %Q{https_proxy "#{config[:bootstrap_proxy]}"\n}
+ client_rb << %Q{no_proxy "#{config[:bootstrap_no_proxy]}"\n} if config[:bootstrap_no_proxy]
end
- if knife_config[:bootstrap_no_proxy]
- client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n}
+ if config[:bootstrap_no_proxy]
+ client_rb << %Q{no_proxy "#{config[:bootstrap_no_proxy]}"\n}
end
- if @config[:secret]
+ if config[:secret]
client_rb << %Q{encrypted_data_bag_secret "#{ChefConfig::Config.etc_chef_dir(true)}/encrypted_data_bag_secret"\n}
end
@@ -131,7 +133,7 @@ class Chef
client_rb << %Q{trusted_certs_dir "#{ChefConfig::Config.etc_chef_dir(true)}/trusted_certs"\n}
end
- if Chef::Config[:fips]
+ if chef_config[:fips]
client_rb << "fips true\n"
end
@@ -139,18 +141,18 @@ class Chef
end
def get_log_location
- if @chef_config[:config_log_location].equal?(:win_evt)
- %Q{:#{@chef_config[:config_log_location]}\n}
- elsif @chef_config[:config_log_location].equal?(:syslog)
+ if chef_config[:config_log_location].equal?(:win_evt)
+ %Q{:#{chef_config[:config_log_location]}\n}
+ elsif chef_config[:config_log_location].equal?(:syslog)
raise "syslog is not supported for log_location on Windows OS\n"
- elsif @chef_config[:config_log_location].equal?(STDOUT)
+ elsif chef_config[:config_log_location].equal?(STDOUT)
"STDOUT\n"
- elsif @chef_config[:config_log_location].equal?(STDERR)
+ elsif chef_config[:config_log_location].equal?(STDERR)
"STDERR\n"
- elsif @chef_config[:config_log_location].nil? || @chef_config[:config_log_location].empty?
+ elsif chef_config[:config_log_location].nil? || chef_config[:config_log_location].empty?
"STDOUT\n"
- elsif @chef_config[:config_log_location]
- %Q{"#{@chef_config[:config_log_location]}"\n}
+ elsif chef_config[:config_log_location]
+ %Q{"#{chef_config[:config_log_location]}"\n}
else
"STDOUT\n"
end
@@ -270,15 +272,15 @@ class Chef
# Build a URL to query www.chef.io that will redirect to the correct
# Chef Infra msi download.
def msi_url(machine_os = nil, machine_arch = nil, download_context = nil)
- if @config[:msi_url].nil? || @config[:msi_url].empty?
+ if config[:msi_url].nil? || config[:msi_url].empty?
url = "https://www.chef.io/chef/download?p=windows"
url += "&pv=#{machine_os}" unless machine_os.nil?
url += "&m=#{machine_arch}" unless machine_arch.nil?
url += "&DownloadContext=#{download_context}" unless download_context.nil?
- url += "&channel=#{@config[:channel]}"
+ url += "&channel=#{config[:channel]}"
url += "&v=#{version_to_install}"
else
- @config[:msi_url]
+ config[:msi_url]
end
end
@@ -303,8 +305,8 @@ class Chef
# This string should contain both the commands necessary to both create the files, as well as their content
def trusted_certs_content
content = ""
- if @chef_config[:trusted_certs_dir]
- Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(@chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
+ if chef_config[:trusted_certs_dir]
+ Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
content << "> #{bootstrap_directory}/trusted_certs/#{File.basename(cert)} (\n" +
escape_and_echo(IO.read(File.expand_path(cert))) + "\n)\n"
end
@@ -314,8 +316,8 @@ class Chef
def client_d_content
content = ""
- if @chef_config[:client_d_dir] && File.exist?(@chef_config[:client_d_dir])
- root = Pathname(@chef_config[:client_d_dir])
+ if chef_config[:client_d_dir] && File.exist?(chef_config[:client_d_dir])
+ root = Pathname(chef_config[:client_d_dir])
root.find do |f|
relative = f.relative_path_from(root)
if f != root
diff --git a/lib/chef/knife/data_bag_secret_options.rb b/lib/chef/knife/data_bag_secret_options.rb
index 213e02c376..8f9f96502f 100644
--- a/lib/chef/knife/data_bag_secret_options.rb
+++ b/lib/chef/knife/data_bag_secret_options.rb
@@ -34,17 +34,13 @@ class Chef
# are provided.
def self.included(base)
- base.option :secret,
+ base.option :cl_secret,
long: "--secret SECRET",
- description: "The secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret'.",
- # Need to store value from command line in separate variable - knife#merge_configs populates same keys
- # on config object from
- proc: Proc.new { |s| set_cl_secret(s) }
+ description: "The secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret'."
- base.option :secret_file,
+ base.option :cl_secret_file,
long: "--secret-file SECRET_FILE",
- description: "A file containing the secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret_file'.",
- proc: Proc.new { |sf| set_cl_secret_file(sf) }
+ description: "A file containing the secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret_file'."
base.option :encrypt,
long: "--encrypt",
@@ -66,25 +62,25 @@ class Chef
# IE, if we are not running 'knife data bag *' we don't need to load 'chef/encrypted_data_bag_item'
require_relative "../encrypted_data_bag_item"
- if has_cl_secret?
- config[:secret]
- elsif has_cl_secret_file?
- Chef::EncryptedDataBagItem.load_secret(config[:secret_file])
- elsif secret = knife_config[:secret]
+ if config[:cl_secret]
+ config[:cl_secret]
+ elsif config[:cl_secret_file]
+ Chef::EncryptedDataBagItem.load_secret(config[:cl_secret_file])
+ elsif secret = config[:secret]
secret
else
- secret_file = knife_config[:secret_file]
+ secret_file = config[:secret_file]
Chef::EncryptedDataBagItem.load_secret(secret_file)
end
end
def validate_secrets
- if has_cl_secret? && has_cl_secret_file?
+ if config[:cl_secret] && config[:cl_secret_file]
ui.fatal("Please specify only one of --secret, --secret-file")
exit(1)
end
- if knife_config[:secret] && knife_config[:secret_file]
+ if config[:secret] && config[:secret_file]
ui.fatal("Please specify only one of 'secret' or 'secret_file' in your config file")
exit(1)
end
@@ -98,41 +94,26 @@ class Chef
def base_encryption_secret_provided?(need_encrypt_flag = true)
validate_secrets
- return true if has_cl_secret? || has_cl_secret_file?
+ return true if config[:cl_secret] || config[:cl_secret_file]
if need_encrypt_flag
if config[:encrypt]
- unless knife_config[:secret] || knife_config[:secret_file]
+ unless config[:secret] || config[:secret_file]
ui.fatal("No secret or secret_file specified in config, unable to encrypt item.")
exit(1)
end
return true
end
return false
- elsif knife_config[:secret] || knife_config[:secret_file]
+ elsif config[:secret] || config[:secret_file]
# Certain situations (show and bootstrap) don't need a --encrypt flag to use the config file secret
return true
end
false
end
- def has_cl_secret?
- Chef::Config[:knife].key?(:cl_secret)
- end
-
- def self.set_cl_secret(s)
- Chef::Config[:knife][:cl_secret] = s
- end
-
- def has_cl_secret_file?
- Chef::Config[:knife].key?(:cl_secret_file)
- end
-
- def self.set_cl_secret_file(sf)
- Chef::Config[:knife][:cl_secret_file] = sf
- end
-
def knife_config
+ Chef.deprecated(:knife_bootstrap_apis, "The `knife_config` bootstrap helper has been deprecated, use the properly merged `config` helper instead")
Chef::Config.key?(:knife) ? Chef::Config[:knife] : {}
end
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index a959dc887d..837ba780f5 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -66,7 +66,7 @@ class Chef
long: "--ssh-user USERNAME",
description: "The ssh username."
- option :ssh_password_ng,
+ option :ssh_password,
short: "-P [PASSWORD]",
long: "--ssh-password [PASSWORD]",
description: "The ssh password - will prompt if flag is specified but no password is given.",
@@ -79,20 +79,20 @@ class Chef
short: "-p PORT",
long: "--ssh-port PORT",
description: "The ssh port.",
- proc: Proc.new { |key| Chef::Config[:knife][:ssh_port] = key.strip }
+ proc: Proc.new { |key| key.strip }
option :ssh_timeout,
short: "-t SECONDS",
long: "--ssh-timeout SECONDS",
description: "The ssh connection timeout.",
- proc: Proc.new { |key| Chef::Config[:knife][:ssh_timeout] = key.strip.to_i },
+ proc: Proc.new { |key| key.strip.to_i },
default: 120
option :ssh_gateway,
short: "-G GATEWAY",
long: "--ssh-gateway GATEWAY",
description: "The ssh gateway.",
- proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key.strip }
+ proc: Proc.new { |key| key.strip }
option :ssh_gateway_identity,
long: "--ssh-gateway-identity SSH_GATEWAY_IDENTITY",
@@ -125,7 +125,7 @@ class Chef
option :duplicated_fqdns,
long: "--duplicated-fqdns",
description: "Behavior if FQDNs are duplicated, ignored by default.",
- proc: Proc.new { |key| Chef::Config[:knife][:duplicated_fqdns] = key.strip.to_sym },
+ proc: Proc.new { |key| key.strip.to_sym },
default: :ignore
option :tmux_split,
@@ -149,7 +149,6 @@ class Chef
end
def configure_gateway
- config[:ssh_gateway] ||= Chef::Config[:knife][:ssh_gateway]
if config[:ssh_gateway]
gw_host, gw_user = config[:ssh_gateway].split("@").reverse
gw_host, gw_port = gw_host.split(":")
@@ -273,7 +272,6 @@ class Chef
def session_options(host, port, user = nil, gateway: false)
ssh_config = Net::SSH.configuration_for(host, true)
{}.tap do |opts|
- # Chef::Config[:knife][:ssh_user] is parsed in #configure_user and written to config[:ssh_user]
opts[:user] = user || config[:ssh_user] || ssh_config[:user]
if !gateway && config[:ssh_identity_file]
opts[:keys] = File.expand_path(config[:ssh_identity_file])
@@ -308,10 +306,8 @@ class Chef
Chef::Log.debug("Adding #{host}")
session_opts = session_options(host, ssh_port, gateway: false)
# Handle port overrides for the main connection.
- session_opts[:port] = Chef::Config[:knife][:ssh_port] if Chef::Config[:knife][:ssh_port]
session_opts[:port] = config[:ssh_port] if config[:ssh_port]
# Handle connection timeout
- session_opts[:timeout] = Chef::Config[:knife][:ssh_timeout] if Chef::Config[:knife][:ssh_timeout]
session_opts[:timeout] = config[:ssh_timeout] if config[:ssh_timeout]
# Handle session prefix
session_opts[:properties] = { prefix: prefix }
@@ -547,7 +543,7 @@ class Chef
end
def get_stripped_unfrozen_value(value)
- return nil if value.nil?
+ return nil unless value
value.strip
end
@@ -557,37 +553,22 @@ class Chef
Chef::Config[:knife][:ssh_user])
end
- # This is a bit overly complicated because of the way we want knife ssh to work with -P causing a password prompt for
- # the user, but we have to be conscious that this code gets included in knife bootstrap and knife * server create as
- # well. We want to change the semantics so that the default is false and 'nil' means -P without an argument on the
- # command line. But the other utilities expect nil to be the default and we can't prompt in that case. So we effectively
- # use ssh_password_ng to determine if we're coming from knife ssh or from the other utilities. The other utilities can
- # also be patched to use ssh_password_ng easily as long they follow the convention that the default is false.
def configure_password
- if config.key?(:ssh_password_ng) && config[:ssh_password_ng].nil?
- # If the parameter is called on the command line with no value
- # it will set :ssh_password_ng = nil
- # This is where we want to trigger a prompt for password
+ if config.key?(:ssh_password) && config[:ssh_password].nil?
+ # if we have an actual nil that means someone called "--ssh-password" with no value, so we prompt for a password
config[:ssh_password] = get_password
else
- # if ssh_password_ng is false then it has not been set at all, and we may be in knife ec2 and still
- # using an old config[:ssh_password]. this is backwards compatibility. all knife cloud plugins should
- # be updated to use ssh_password_ng with a default of false and ssh_password should be retired, (but
- # we'll still need to use the ssh_password out of knife.rb if we find that).
- ssh_password = config.key?(:ssh_password_ng) ? config[:ssh_password_ng] : config[:ssh_password]
- # Otherwise, the password has either been specified on the command line,
- # in knife.rb, or key based auth will be attempted
- config[:ssh_password] = get_stripped_unfrozen_value(ssh_password ||
- Chef::Config[:knife][:ssh_password])
+ # the false default of ssh_password results in a nil here
+ config[:ssh_password] = get_stripped_unfrozen_value(config[:ssh_password])
end
end
def configure_ssh_identity_file
- config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || Chef::Config[:knife][:ssh_identity_file])
+ config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file])
end
def configure_ssh_gateway_identity
- config[:ssh_gateway_identity] = get_stripped_unfrozen_value(config[:ssh_gateway_identity] || Chef::Config[:knife][:ssh_gateway_identity])
+ config[:ssh_gateway_identity] = get_stripped_unfrozen_value(config[:ssh_gateway_identity])
end
def run
diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb
index f157c60b41..530cf791f7 100644
--- a/lib/chef/knife/status.rb
+++ b/lib/chef/knife/status.rb
@@ -85,7 +85,7 @@ class Chef
end
output(all_nodes.sort do |n1, n2|
- if config[:sort_reverse] || Chef::Config[:knife][:sort_status_reverse]
+ if config[:sort_reverse] || config[:sort_status_reverse]
(n2["ohai_time"] || 0) <=> (n1["ohai_time"] || 0)
else
(n1["ohai_time"] || 0) <=> (n2["ohai_time"] || 0)
diff --git a/lib/chef/knife/supermarket_download.rb b/lib/chef/knife/supermarket_download.rb
index 75dda0641e..5acd733b78 100644
--- a/lib/chef/knife/supermarket_download.rb
+++ b/lib/chef/knife/supermarket_download.rb
@@ -42,8 +42,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
def run
if current_cookbook_deprecated?
diff --git a/lib/chef/knife/supermarket_install.rb b/lib/chef/knife/supermarket_install.rb
index 8813f3bf6e..55b32a1774 100644
--- a/lib/chef/knife/supermarket_install.rb
+++ b/lib/chef/knife/supermarket_install.rb
@@ -63,8 +63,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
attr_reader :cookbook_name
attr_reader :vendor_path
diff --git a/lib/chef/knife/supermarket_list.rb b/lib/chef/knife/supermarket_list.rb
index 088f577457..7dca8d031b 100644
--- a/lib/chef/knife/supermarket_list.rb
+++ b/lib/chef/knife/supermarket_list.rb
@@ -34,8 +34,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
option :sort_by,
long: "--sort-by SORT",
diff --git a/lib/chef/knife/supermarket_search.rb b/lib/chef/knife/supermarket_search.rb
index 227a0df456..57befaed35 100644
--- a/lib/chef/knife/supermarket_search.rb
+++ b/lib/chef/knife/supermarket_search.rb
@@ -28,8 +28,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
def run
output(search_cookbook(name_args[0]))
diff --git a/lib/chef/knife/supermarket_share.rb b/lib/chef/knife/supermarket_share.rb
index 1082cd01d2..7d3523dfb8 100644
--- a/lib/chef/knife/supermarket_share.rb
+++ b/lib/chef/knife/supermarket_share.rb
@@ -51,8 +51,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
def run
config[:cookbook_path] ||= Chef::Config[:cookbook_path]
diff --git a/lib/chef/knife/supermarket_show.rb b/lib/chef/knife/supermarket_show.rb
index 3db1f87fe7..7237cf0bc7 100644
--- a/lib/chef/knife/supermarket_show.rb
+++ b/lib/chef/knife/supermarket_show.rb
@@ -29,8 +29,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
def run
output(format_for_display(get_cookbook_data))
diff --git a/lib/chef/knife/supermarket_unshare.rb b/lib/chef/knife/supermarket_unshare.rb
index 1ae4d5108c..0904a70f57 100644
--- a/lib/chef/knife/supermarket_unshare.rb
+++ b/lib/chef/knife/supermarket_unshare.rb
@@ -33,8 +33,7 @@ class Chef
short: "-m SUPERMARKET_SITE",
long: "--supermarket-site SUPERMARKET_SITE",
description: "The URL of the Supermarket site.",
- default: "https://supermarket.chef.io",
- proc: Proc.new { |supermarket| Chef::Config[:knife][:supermarket_site] = supermarket }
+ default: "https://supermarket.chef.io"
def run
@cookbook_name = @name_args[0]
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" }