diff options
author | Tim Smith <tsmith@chef.io> | 2020-04-17 10:29:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-17 10:29:16 -0700 |
commit | d025430baa0360a8278be40056e773a27f9e97d2 (patch) | |
tree | dc681fc2310934b29afc9526dfc064121e76ae67 /lib | |
parent | acdebb10de9e9c2e2b6b1fae1c9d112e89f89844 (diff) | |
parent | d7452360adb80e383b4886246990dbe46d3387c2 (diff) | |
download | chef-d025430baa0360a8278be40056e773a27f9e97d2.tar.gz |
Merge pull request #9646 from chef/lcg/bootstrap-options-cleanup
Knife bootstrap options cleanup
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/deprecated.rb | 4 | ||||
-rw-r--r-- | lib/chef/knife.rb | 46 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap.rb | 179 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap/chef_vault_handler.rb | 20 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap/client_builder.rb | 42 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap/templates/chef-full.erb | 22 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb | 16 | ||||
-rw-r--r-- | lib/chef/knife/core/bootstrap_context.rb | 122 | ||||
-rw-r--r-- | lib/chef/knife/core/generic_presenter.rb | 7 | ||||
-rw-r--r-- | lib/chef/knife/core/windows_bootstrap_context.rb | 84 | ||||
-rw-r--r-- | lib/chef/knife/data_bag_secret_options.rb | 51 | ||||
-rw-r--r-- | lib/chef/knife/ssh.rb | 43 | ||||
-rw-r--r-- | lib/chef/knife/status.rb | 2 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_download.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_install.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_list.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_search.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_share.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_show.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/supermarket_unshare.rb | 3 |
20 files changed, 313 insertions, 346 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] |