diff options
52 files changed, 484 insertions, 344 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index c2ce04d75f..36a013d53c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,20 @@ <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ --> -<!-- latest_release 15.0.251 --> -## [v15.0.251](https://github.com/chef/chef/tree/v15.0.251) (2019-05-01) +<!-- latest_release 15.0.258 --> +## [v15.0.258](https://github.com/chef/chef/tree/v15.0.258) (2019-05-03) #### Merged Pull Requests -- Update to Ruby 2.6.3 [#8446](https://github.com/chef/chef/pull/8446) ([tas50](https://github.com/tas50)) +- Update more brand names to current [#8454](https://github.com/chef/chef/pull/8454) ([tas50](https://github.com/tas50)) <!-- latest_release --> <!-- release_rollup --> ### Changes since latest stable release #### Merged Pull Requests +- Update more brand names to current [#8454](https://github.com/chef/chef/pull/8454) ([tas50](https://github.com/tas50)) <!-- 15.0.258 --> +- Add connstant for Chef Server and improve help messaging [#8452](https://github.com/chef/chef/pull/8452) ([tas50](https://github.com/tas50)) <!-- 15.0.257 --> +- Fixed empty value for knife status long output [#8415](https://github.com/chef/chef/pull/8415) ([vijaymmali1990](https://github.com/vijaymmali1990)) <!-- 15.0.256 --> +- [CHEF-8432] Ensure default protocol is used properly. Use correct 'require' before accessing Net::SSH constants. [#8440](https://github.com/chef/chef/pull/8440) ([marcparadise](https://github.com/marcparadise)) <!-- 15.0.255 --> +- Replace Chef Client by its constant in Chef::Dist [#8448](https://github.com/chef/chef/pull/8448) ([Tensibai](https://github.com/Tensibai)) <!-- 15.0.254 --> - Update to Ruby 2.6.3 [#8446](https://github.com/chef/chef/pull/8446) ([tas50](https://github.com/tas50)) <!-- 15.0.251 --> - Remove old maintainer gems from the Gemfile [#8445](https://github.com/chef/chef/pull/8445) ([tas50](https://github.com/tas50)) <!-- 15.0.250 --> - [CHEF-8422] Fix incorrect deprecation warnings [#8429](https://github.com/chef/chef/pull/8429) ([marcparadise](https://github.com/marcparadise)) <!-- 15.0.249 --> diff --git a/Gemfile.lock b/Gemfile.lock index b5b08571ec..fe19f48313 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -27,11 +27,11 @@ GIT PATH remote: . specs: - chef (15.0.253) + chef (15.0.258) addressable bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) - chef-config (= 15.0.253) + chef-config (= 15.0.258) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -56,11 +56,11 @@ PATH train-core (~> 2.0, >= 2.0.12) tty-screen (~> 0.6) uuidtools (~> 2.1.5) - chef (15.0.253-universal-mingw32) + chef (15.0.258-universal-mingw32) addressable bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) - chef-config (= 15.0.253) + chef-config (= 15.0.258) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -101,13 +101,13 @@ PATH PATH remote: chef-bin specs: - chef-bin (15.0.253) - chef (= 15.0.253) + chef-bin (15.0.258) + chef (= 15.0.258) PATH remote: chef-config specs: - chef-config (15.0.253) + chef-config (15.0.258) addressable fuzzyurl mixlib-config (>= 2.2.12, < 4.0) @@ -1 +1 @@ -15.0.253
\ No newline at end of file +15.0.258
\ No newline at end of file diff --git a/chef-bin/lib/chef-bin/version.rb b/chef-bin/lib/chef-bin/version.rb index d9dd728bbe..23420a3a29 100644 --- a/chef-bin/lib/chef-bin/version.rb +++ b/chef-bin/lib/chef-bin/version.rb @@ -21,7 +21,7 @@ module ChefBin CHEFBIN_ROOT = File.expand_path("../..", __FILE__) - VERSION = "15.0.253".freeze + VERSION = "15.0.258".freeze end # diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index 454f05932a..6224865210 100644 --- a/chef-config/lib/chef-config/version.rb +++ b/chef-config/lib/chef-config/version.rb @@ -21,7 +21,7 @@ module ChefConfig CHEFCONFIG_ROOT = File.expand_path("../..", __FILE__) - VERSION = "15.0.253".freeze + VERSION = "15.0.258".freeze end # diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb index c25f0ed46e..34f0973b40 100644 --- a/lib/chef/application/apply.rb +++ b/lib/chef/application/apply.rb @@ -35,49 +35,49 @@ class Chef::Application::Apply < Chef::Application option :execute, short: "-e RECIPE_TEXT", long: "--execute RECIPE_TEXT", - description: "Execute resources supplied in a string", + description: "Execute resources supplied in a string.", proc: nil option :stdin, short: "-s", long: "--stdin", - description: "Execute resources read from STDIN", + description: "Execute resources read from STDIN.", boolean: true option :json_attribs, short: "-j JSON_ATTRIBS", long: "--json-attributes JSON_ATTRIBS", - description: "Load attributes from a JSON file or URL", + description: "Load attributes from a JSON file or URL.", proc: nil option :force_logger, long: "--force-logger", - description: "Use logger output instead of formatter output", + description: "Use logger output instead of formatter output.", boolean: true, default: false option :force_formatter, long: "--force-formatter", - description: "Use formatter output instead of logger output", + description: "Use formatter output instead of logger output.", boolean: true, default: false option :formatter, short: "-F FORMATTER", long: "--format FORMATTER", - description: "output format to use", + description: "The output format to use.", proc: lambda { |format| Chef::Config.add_formatter(format) } option :log_level, short: "-l LEVEL", long: "--log_level LEVEL", - description: "Set the log level (trace, debug, info, warn, error, fatal)", + description: "Set the log level (trace, debug, info, warn, error, fatal).", proc: lambda { |l| l.to_sym } option :help, short: "-h", long: "--help", - description: "Show this message", + description: "Show this help message.", on: :tail, boolean: true, show_options: true, @@ -86,7 +86,7 @@ class Chef::Application::Apply < Chef::Application option :version, short: "-v", long: "--version", - description: "Show #{Chef::Dist::PRODUCT} version", + description: "Show #{Chef::Dist::PRODUCT} version.", boolean: true, proc: lambda { |v| puts "#{Chef::Dist::PRODUCT}: #{::Chef::VERSION}" }, exit: 0 @@ -94,12 +94,12 @@ class Chef::Application::Apply < Chef::Application option :why_run, short: "-W", long: "--why-run", - description: "Enable whyrun mode", + description: "Enable whyrun mode.", boolean: true option :profile_ruby, long: "--[no-]profile-ruby", - description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only)", + description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only).", boolean: true, default: false @@ -107,11 +107,11 @@ class Chef::Application::Apply < Chef::Application long: "--[no-]color", boolean: true, default: true, - description: "Use colored output, defaults to enabled" + description: "Use colored output, defaults to enabled." option :minimal_ohai, long: "--minimal-ohai", - description: "Only run the bare minimum ohai plugins #{Chef::Dist::CLIENT} needs to function", + description: "Only run the bare minimum Ohai plugins #{Chef::Dist::PRODUCT} needs to function.", boolean: true attr_reader :json_attribs diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index ee3e0f7f04..390acfba04 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -2,7 +2,7 @@ # Author:: AJ Christensen (<aj@chef.io) # Author:: Christopher Brown (<cb@chef.io>) # Author:: Mark Mzyk (mmzyk@chef.io) -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,11 +41,11 @@ class Chef::Application::Client < Chef::Application option :config_file, short: "-c CONFIG", long: "--config CONFIG", - description: "The configuration file to use" + description: "The configuration file to use." option :config_option, long: "--config-option OPTION=VALUE", - description: "Override a single configuration option", + description: "Override a single configuration option.", proc: lambda { |option, existing| (existing ||= []) << option existing @@ -54,24 +54,24 @@ class Chef::Application::Client < Chef::Application option :formatter, short: "-F FORMATTER", long: "--format FORMATTER", - description: "output format to use", + description: "The output format to use.", proc: lambda { |format| Chef::Config.add_formatter(format) } option :force_logger, long: "--force-logger", - description: "Use logger output instead of formatter output", + description: "Use logger output instead of formatter output.", boolean: true, default: false option :force_formatter, long: "--force-formatter", - description: "Use formatter output instead of logger output", + description: "Use formatter output instead of logger output.", boolean: true, default: false option :profile_ruby, long: "--[no-]profile-ruby", - description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only)", + description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only).", boolean: true, default: false @@ -79,24 +79,24 @@ class Chef::Application::Client < Chef::Application long: "--[no-]color", boolean: true, default: true, - description: "Use colored output, defaults to enabled" + description: "Use colored output, defaults to enabled." option :log_level, short: "-l LEVEL", long: "--log_level LEVEL", - description: "Set the log level (auto, trace, debug, info, warn, error, fatal)", + description: "Set the log level (auto, trace, debug, info, warn, error, fatal).", proc: lambda { |l| l.to_sym } option :log_location, short: "-L LOGLOCATION", long: "--logfile LOGLOCATION", - description: "Set the log file location, defaults to STDOUT - recommended for daemonizing", + description: "Set the log file location, defaults to STDOUT - recommended for daemonizing.", proc: nil option :help, short: "-h", long: "--help", - description: "Show this message", + description: "Show this help message.", on: :tail, boolean: true, show_options: true, @@ -105,20 +105,20 @@ class Chef::Application::Client < Chef::Application option :user, short: "-u USER", long: "--user USER", - description: "User to set privilege to", + description: "User to set privilege to.", proc: nil option :group, short: "-g GROUP", long: "--group GROUP", - description: "Group to set privilege to", + description: "Group to set privilege to.", proc: nil unless Chef::Platform.windows? option :daemonize, short: "-d [WAIT]", long: "--daemonize [WAIT]", - description: "Daemonize the process. Accepts an optional integer which is the " \ + description: "Daemonize the process. Accepts an optional integer which is the " \ "number of seconds to wait before the first daemonized run.", proc: lambda { |wait| wait =~ /^\d+$/ ? wait.to_i : true } end @@ -126,75 +126,75 @@ class Chef::Application::Client < Chef::Application option :pid_file, short: "-P PID_FILE", long: "--pid PIDFILE", - description: "Set the PID file location, for the #{Chef::Dist::CLIENT} daemon process. Defaults to /tmp/chef-client.pid", + description: "Set the PID file location, for the #{Chef::Dist::CLIENT} daemon process. Defaults to /tmp/chef-client.pid.", proc: nil option :lockfile, long: "--lockfile LOCKFILE", - description: "Set the lockfile location. Prevents multiple client processes from converging at the same time", + description: "Set the lockfile location. Prevents multiple client processes from converging at the same time.", proc: nil option :interval, short: "-i SECONDS", long: "--interval SECONDS", - description: "Run #{Chef::Dist::CLIENT} periodically, in seconds", + description: "Run #{Chef::Dist::CLIENT} periodically, in seconds.", proc: lambda { |s| s.to_i } option :once, long: "--once", - description: "Cancel any interval or splay options, run #{Chef::Dist::CLIENT} once and exit", + description: "Cancel any interval or splay options, run #{Chef::Dist::CLIENT} once and exit.", boolean: true option :json_attribs, short: "-j JSON_ATTRIBS", long: "--json-attributes JSON_ATTRIBS", - description: "Load attributes from a JSON file or URL", + description: "Load attributes from a JSON file or URL.", proc: nil option :node_name, short: "-N NODE_NAME", long: "--node-name NODE_NAME", - description: "The node name for this client", + description: "The node name for this client.", proc: nil option :splay, short: "-s SECONDS", long: "--splay SECONDS", - description: "The splay time for running at intervals, in seconds", + description: "The splay time for running at intervals, in seconds.", proc: lambda { |s| s.to_i } option :chef_server_url, short: "-S CHEFSERVERURL", long: "--server CHEFSERVERURL", - description: "The #{Chef::Dist::PRODUCT} server URL", + description: "The #{Chef::Dist::SERVER_PRODUCT} URL.", proc: nil option :validation_key, short: "-K KEY_FILE", long: "--validation_key KEY_FILE", - description: "Set the validation key file location, used for registering new clients", + description: "Set the validation key file location, used for registering new clients.", proc: nil option :client_key, short: "-k KEY_FILE", long: "--client_key KEY_FILE", - description: "Set the client key file location", + description: "Set the client key file location.", proc: nil option :named_run_list, short: "-n NAMED_RUN_LIST", long: "--named-run-list NAMED_RUN_LIST", - description: "Use a policyfile's named run list instead of the default run list" + description: "Use a policyfile's named run list instead of the default run list." option :environment, short: "-E ENVIRONMENT", long: "--environment ENVIRONMENT", - description: "Set the #{Chef::Dist::PRODUCT} Environment on the node" + description: "Set the #{Chef::Dist::PRODUCT} environment on the node." option :version, short: "-v", long: "--version", - description: "Show #{Chef::Dist::PRODUCT} version", + description: "Show #{Chef::Dist::PRODUCT} version.", boolean: true, proc: lambda { |v| puts "#{Chef::Dist::PRODUCT}: #{::Chef::VERSION}" }, exit: 0 @@ -202,7 +202,7 @@ class Chef::Application::Client < Chef::Application option :override_runlist, short: "-o RunlistItem,RunlistItem...", long: "--override-runlist RunlistItem,RunlistItem...", - description: "Replace current run list with specified items for a single run", + description: "Replace current run list with specified items for a single run.", proc: lambda { |items| items = items.split(",") items.compact.map do |item| @@ -213,7 +213,7 @@ class Chef::Application::Client < Chef::Application option :runlist, short: "-r RunlistItem,RunlistItem...", long: "--runlist RunlistItem,RunlistItem...", - description: "Permanently replace current run list with specified items", + description: "Permanently replace current run list with specified items.", proc: lambda { |items| items = items.split(",") items.compact.map do |item| @@ -223,13 +223,13 @@ class Chef::Application::Client < Chef::Application option :why_run, short: "-W", long: "--why-run", - description: "Enable whyrun mode", + description: "Enable whyrun mode.", boolean: true option :client_fork, short: "-f", long: "--[no-]fork", - description: "Fork client" + description: "Fork #{Chef::Dist::CLIENT} process." option :recipe_url, long: "--recipe-url=RECIPE_URL", @@ -238,26 +238,26 @@ class Chef::Application::Client < Chef::Application option :enable_reporting, short: "-R", long: "--enable-reporting", - description: "Enable reporting data collection for #{Chef::Dist::PRODUCT} runs", + description: "Enable reporting data collection for #{Chef::Dist::PRODUCT} runs.", boolean: true option :local_mode, short: "-z", long: "--local-mode", - description: "Point #{Chef::Dist::CLIENT} at local repository", + description: "Point #{Chef::Dist::CLIENT} at local repository.", boolean: true option :chef_zero_host, long: "--chef-zero-host HOST", - description: "Host to start chef-zero on" + description: "Host to start chef-zero on." option :chef_zero_port, long: "--chef-zero-port PORT", - description: "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works." + description: "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works." option :disable_config, long: "--disable-config", - description: "Refuse to load a config file and use defaults. This is for development and not a stable API", + description: "Refuse to load a config file and use defaults. This is for development and not a stable API.", boolean: true option :run_lock_timeout, @@ -269,33 +269,33 @@ class Chef::Application::Client < Chef::Application option :fatal_windows_admin_check, short: "-A", long: "--fatal-windows-admin-check", - description: "Fail the run when #{Chef::Dist::CLIENT} doesn't have administrator privileges on Windows", + description: "Fail the run when #{Chef::Dist::CLIENT} doesn't have administrator privileges on Windows.", boolean: true end option :minimal_ohai, long: "--minimal-ohai", - description: "Only run the bare minimum ohai plugins #{Chef::Dist::CLIENT} needs to function", + description: "Only run the bare minimum Ohai plugins #{Chef::Dist::PRODUCT} needs to function.", boolean: true option :listen, long: "--[no-]listen", - description: "Whether a local mode (-z) server binds to a port", + description: "Whether a local mode (-z) server binds to a port.", boolean: false option :fips, long: "--[no-]fips", - description: "Enable fips mode", + description: "Enable FIPS mode.", boolean: true option :delete_entire_chef_repo, long: "--delete-entire-chef-repo", - description: "DANGEROUS: does what it says, only useful with --recipe-url", + description: "DANGEROUS: does what it says, only useful with --recipe-url.", boolean: true option :skip_cookbook_sync, long: "--[no-]skip-cookbook-sync", - description: "Use cached cookbooks without overwriting local differences from the server", + description: "Use cached cookbooks without overwriting local differences from the #{Chef::Dist::SERVER_PRODUCT}.", boolean: false IMMEDIATE_RUN_SIGNAL = "1".freeze @@ -504,7 +504,7 @@ class Chef::Application::Client < Chef::Application end def unforked_interval_error_message - "Unforked #{Chef::Dist::CLIENT} interval runs are disabled in #{Chef::Dist::PRODUCT} 12." + + "Unforked #{Chef::Dist::CLIENT} interval runs are disabled by default." + "\nConfiguration settings:" + ("\n interval = #{Chef::Config[:interval]} seconds" if Chef::Config[:interval]).to_s + "\nEnable #{Chef::Dist::CLIENT} interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options." diff --git a/lib/chef/application/exit_code.rb b/lib/chef/application/exit_code.rb index 6c9618fcb4..5330db2456 100644 --- a/lib/chef/application/exit_code.rb +++ b/lib/chef/application/exit_code.rb @@ -1,6 +1,6 @@ # # Author:: Steven Murawski (<smurawski@chef.io>) -# Copyright:: Copyright 2016, Chef Software, Inc. +# Copyright:: Copyright 2016-2019, Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,7 @@ class Chef # These are the exit codes defined in Chef RFC 062 # https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md class ExitCode + require "chef/dist" # -1 is defined as DEPRECATED_FAILURE in RFC 062, so it is # not enumerated in an active constant. @@ -143,10 +144,10 @@ class Chef end def non_standard_exit_code_warning(exit_code) - "Chef attempted to exit with a non-standard exit code of #{exit_code}." \ - " Chef RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) defines the" \ - " exit codes that should be used with Chef. Chef::Application::ExitCode defines valid exit codes" \ - " Non-standard exit codes are redefined as GENERIC_FAILURE." + "#{Chef::Dist::CLIENT} attempted to exit with a non-standard exit code of #{exit_code}." \ + " The Chef-Client Exit Codes design document (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md)" \ + " defines the exit codes that should be used with Chef. Chef::Application::ExitCode defines" \ + " valid exit codes Non-standard exit codes are redefined as GENERIC_FAILURE." end end diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb index bdf1b7e7a7..52d447891f 100644 --- a/lib/chef/application/knife.rb +++ b/lib/chef/application/knife.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,12 +31,12 @@ class Chef::Application::Knife < Chef::Application option :config_file, short: "-c CONFIG", long: "--config CONFIG", - description: "The configuration file to use", + description: "The configuration file to use.", proc: lambda { |path| File.expand_path(path, Dir.pwd) } option :config_option, long: "--config-option OPTION=VALUE", - description: "Override a single configuration option", + description: "Override a single configuration option.", proc: lambda { |option, existing| (existing ||= []) << option existing @@ -46,7 +46,7 @@ class Chef::Application::Knife < Chef::Application option :verbosity, short: "-V", long: "--verbose", - description: "More verbose output. Use twice for max verbosity", + description: "More verbose output. Use twice for max verbosity.", proc: Proc.new { verbosity_level += 1 }, default: 0 @@ -54,104 +54,104 @@ class Chef::Application::Knife < Chef::Application long: "--[no-]color", boolean: true, default: true, - description: "Use colored output, defaults to enabled" + description: "Use colored output, defaults to enabled." option :environment, short: "-E ENVIRONMENT", long: "--environment ENVIRONMENT", - description: "Set the #{Chef::Dist::PRODUCT} environment (except for in searches, where this will be flagrantly ignored)" + description: "Set the #{Chef::Dist::PRODUCT} environment (except for in searches, where this will be flagrantly ignored)." option :editor, short: "-e EDITOR", long: "--editor EDITOR", - description: "Set the editor to use for interactive commands", + description: "Set the editor to use for interactive commands.", default: ENV["EDITOR"] option :disable_editing, short: "-d", long: "--disable-editing", - description: "Do not open EDITOR, just accept the data as is", + description: "Do not open EDITOR, just accept the data as is.", boolean: true, default: false option :help, short: "-h", long: "--help", - description: "Show this message", + description: "Show this help message.", on: :tail, boolean: true option :node_name, short: "-u USER", long: "--user USER", - description: "API Client Username" + description: "#{Chef::Dist::SERVER_PRODUCT} API client username." option :client_key, short: "-k KEY", long: "--key KEY", - description: "API Client Key", + description: "#{Chef::Dist::SERVER_PRODUCT} API client key.", proc: lambda { |path| File.expand_path(path, Dir.pwd) } option :chef_server_url, short: "-s URL", long: "--server-url URL", - description: "#{Chef::Dist::PRODUCT} Server URL" + description: "#{Chef::Dist::SERVER_PRODUCT} URL." option :yes, short: "-y", long: "--yes", - description: "Say yes to all prompts for confirmation" + description: "Say yes to all prompts for confirmation." option :defaults, long: "--defaults", - description: "Accept default values for all questions" + description: "Accept default values for all questions." option :print_after, long: "--print-after", - description: "Show the data after a destructive operation" + description: "Show the data after a destructive operation." option :format, short: "-F FORMAT", long: "--format FORMAT", - description: "Which format to use for output", + description: "Which format to use for output.", default: "summary" option :local_mode, short: "-z", long: "--local-mode", - description: "Point knife commands at local repository instead of server", + description: "Point knife commands at local repository instead of #{Chef::Dist::SERVER_PRODUCT}.", boolean: true option :chef_zero_host, long: "--chef-zero-host HOST", - description: "Host to start chef-zero on" + description: "Host to start chef-zero on." option :chef_zero_port, long: "--chef-zero-port PORT", - description: "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works." + description: "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works." option :listen, long: "--[no-]listen", - description: "Whether a local mode (-z) server binds to a port", + description: "Whether a local mode (-z) server binds to a port.", boolean: false option :version, short: "-v", long: "--version", - description: "Show #{Chef::Dist::PRODUCT} version", + description: "Show #{Chef::Dist::PRODUCT} version.", boolean: true, proc: lambda { |v| puts "#{Chef::Dist::PRODUCT}: #{::Chef::VERSION}" }, exit: 0 option :fips, long: "--[no-]fips", - description: "Enable fips mode", + description: "Enable FIPS mode.", boolean: true, default: nil option :profile, long: "--profile PROFILE", - description: "The credentials profile to select" + description: "The credentials profile to select." # Run knife def run diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index 5655b8cdfd..04cc9265ff 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen (<aj@chef.io>) # Author:: Mark Mzyk (mmzyk@chef.io) -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,11 +39,11 @@ class Chef::Application::Solo < Chef::Application short: "-c CONFIG", long: "--config CONFIG", default: Chef::Config.platform_specific_path("/etc/chef/solo.rb"), - description: "The configuration file to use" + description: "The configuration file to use." option :config_option, long: "--config-option OPTION=VALUE", - description: "Override a single configuration option", + description: "Override a single configuration option.", proc: lambda { |option, existing| (existing ||= []) << option existing @@ -52,24 +52,24 @@ class Chef::Application::Solo < Chef::Application option :formatter, short: "-F FORMATTER", long: "--format FORMATTER", - description: "output format to use", + description: "The output format to use.", proc: lambda { |format| Chef::Config.add_formatter(format) } option :force_logger, long: "--force-logger", - description: "Use logger output instead of formatter output", + description: "Use logger output instead of formatter output.", boolean: true, default: false option :force_formatter, long: "--force-formatter", - description: "Use formatter output instead of logger output", + description: "Use formatter output instead of logger output.", boolean: true, default: false option :profile_ruby, long: "--[no-]profile-ruby", - description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only)", + description: "Dump complete Ruby call graph stack of entire #{Chef::Dist::PRODUCT} run (expert only).", boolean: true, default: false @@ -77,24 +77,24 @@ class Chef::Application::Solo < Chef::Application long: "--[no-]color", boolean: true, default: true, - description: "Use colored output, defaults to enabled" + description: "Use colored output, defaults to enabled." option :log_level, short: "-l LEVEL", long: "--log_level LEVEL", - description: "Set the log level (auto, trace, debug, info, warn, error, fatal)", + description: "Set the log level (auto, trace, debug, info, warn, error, fatal).", proc: lambda { |l| l.to_sym } option :log_location, short: "-L LOGLOCATION", long: "--logfile LOGLOCATION", - description: "Set the log file location, defaults to STDOUT - recommended for daemonizing", + description: "Set the log file location, defaults to STDOUT - recommended for daemonizing.", proc: nil option :help, short: "-h", long: "--help", - description: "Show this message", + description: "Show this help message.", on: :tail, boolean: true, show_options: true, @@ -103,50 +103,50 @@ class Chef::Application::Solo < Chef::Application option :user, short: "-u USER", long: "--user USER", - description: "User to set privilege to", + description: "User to set privilege to.", proc: nil option :group, short: "-g GROUP", long: "--group GROUP", - description: "Group to set privilege to", + description: "Group to set privilege to.", proc: nil unless Chef::Platform.windows? option :daemonize, short: "-d", long: "--daemonize", - description: "Daemonize the process", + description: "Daemonize the process.", proc: lambda { |p| true } end option :lockfile, long: "--lockfile LOCKFILE", - description: "Set the lockfile location. Prevents multiple solo processes from converging at the same time", + description: "Set the lockfile location. Prevents multiple solo processes from converging at the same time.", proc: nil option :interval, short: "-i SECONDS", long: "--interval SECONDS", - description: "Run #{Chef::Dist::CLIENT} periodically, in seconds", + description: "Run #{Chef::Dist::CLIENT} periodically, in seconds.", proc: lambda { |s| s.to_i } option :json_attribs, short: "-j JSON_ATTRIBS", long: "--json-attributes JSON_ATTRIBS", - description: "Load attributes from a JSON file or URL", + description: "Load attributes from a JSON file or URL.", proc: nil option :node_name, short: "-N NODE_NAME", long: "--node-name NODE_NAME", - description: "The node name for this client", + description: "The node name for this client.", proc: nil option :splay, short: "-s SECONDS", long: "--splay SECONDS", - description: "The splay time for running at intervals, in seconds", + description: "The splay time for running at intervals, in seconds.", proc: lambda { |s| s.to_i } option :recipe_url, @@ -157,7 +157,7 @@ class Chef::Application::Solo < Chef::Application option :version, short: "-v", long: "--version", - description: "Show #{Chef::Dist::EXEC} version", + description: "Show #{Chef::Dist::PRODUCT} version.", boolean: true, proc: lambda { |v| puts "#{Chef::Dist::PRODUCT}: #{::Chef::VERSION}" }, exit: 0 @@ -165,7 +165,7 @@ class Chef::Application::Solo < Chef::Application option :override_runlist, short: "-o RunlistItem,RunlistItem...", long: "--override-runlist RunlistItem,RunlistItem...", - description: "Replace current run list with specified items for a single run", + description: "Replace current run list with specified items for a single run.", proc: lambda { |items| items = items.split(",") items.compact.map do |item| @@ -176,23 +176,23 @@ class Chef::Application::Solo < Chef::Application option :client_fork, short: "-f", long: "--[no-]fork", - description: "Fork client" + description: "Fork #{Chef::Dist::CLIENT} process." option :why_run, short: "-W", long: "--why-run", - description: "Enable whyrun mode", + description: "Enable whyrun mode.", boolean: true option :ez, long: "--ez", - description: "A memorial for Ezra Zygmuntowicz", + description: "A memorial for Ezra Zygmuntowicz.", boolean: true option :environment, short: "-E ENVIRONMENT", long: "--environment ENVIRONMENT", - description: "Set the #{Chef::Dist::PRODUCT} Environment on the node" + description: "Set the #{Chef::Dist::PRODUCT} environment on the node." option :run_lock_timeout, long: "--run-lock-timeout SECONDS", @@ -201,17 +201,17 @@ class Chef::Application::Solo < Chef::Application option :minimal_ohai, long: "--minimal-ohai", - description: "Only run the bare minimum ohai plugins #{Chef::Dist::PRODUCT} needs to function", + description: "Only run the bare minimum Ohai plugins #{Chef::Dist::PRODUCT} needs to function.", boolean: true option :delete_entire_chef_repo, long: "--delete-entire-chef-repo", - description: "DANGEROUS: does what it says, only useful with --recipe-url", + description: "DANGEROUS: does what it says, only useful with --recipe-url.", boolean: true option :solo_legacy_mode, long: "--legacy-mode", - description: "Run chef-solo in legacy mode", + description: "Run chef-solo in legacy mode.", boolean: true attr_reader :chef_client_json @@ -366,7 +366,7 @@ class Chef::Application::Solo < Chef::Application end def unforked_interval_error_message - "Unforked #{Chef::Dist::CLIENT} interval runs are disabled in #{Chef::Dist::PRODUCT} 12." + + "Unforked #{Chef::Dist::CLIENT} interval runs are disabled by default." + "\nConfiguration settings:" + ("\n interval = #{Chef::Config[:interval]} seconds" if Chef::Config[:interval]).to_s + "\nEnable #{Chef::Dist::CLIENT} interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options." diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb index 3eb4f63129..cba0dc9781 100644 --- a/lib/chef/application/windows_service.rb +++ b/lib/chef/application/windows_service.rb @@ -41,23 +41,23 @@ class Chef short: "-c CONFIG", long: "--config CONFIG", default: "#{ENV['SYSTEMDRIVE']}/chef/client.rb", - description: "" + description: "The configuration file to use for #{Chef::Dist::PRODUCT} runs." option :log_location, short: "-L LOGLOCATION", long: "--logfile LOGLOCATION", - description: "Set the log file location" + description: "Set the log file location." option :splay, short: "-s SECONDS", long: "--splay SECONDS", - description: "The splay time for running at intervals, in seconds", + description: "The splay time for running at intervals, in seconds.", proc: lambda { |s| s.to_i } option :interval, short: "-i SECONDS", long: "--interval SECONDS", - description: "Set the number of seconds to wait between #{Chef::Dist::CLIENT} runs", + description: "Set the number of seconds to wait between #{Chef::Dist::PRODUCT} runs.", proc: lambda { |s| s.to_i } DEFAULT_LOG_LOCATION ||= "#{ENV['SYSTEMDRIVE']}/chef/client.log".freeze @@ -136,7 +136,7 @@ class Chef run_warning_displayed = true end - Chef::Log.trace("Waiting for #{Chef::Dist::CLIENT} run...") + Chef::Log.trace("Waiting for #{Chef::Dist::PRODUCT} run...") sleep 1 end end @@ -150,7 +150,7 @@ class Chef # since this is a PAUSE signal. if @service_action_mutex.locked? - Chef::Log.info("Currently a #{Chef::Dist::CLIENT} run is happening.") + Chef::Log.info("Currently a #{Chef::Dist::PRODUCT} run is happening.") Chef::Log.info("Service will pause once it's completed.") else Chef::Log.info("Service is pausing....") diff --git a/lib/chef/application/windows_service_manager.rb b/lib/chef/application/windows_service_manager.rb index 2ba1861a5b..2646d98624 100644 --- a/lib/chef/application/windows_service_manager.rb +++ b/lib/chef/application/windows_service_manager.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore (<schisamo@chef.io>) -# Copyright:: Copyright 2011-2016, Chef Software, Inc. +# Copyright:: Copyright 2011-2019, Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ if RUBY_PLATFORM =~ /mswin|mingw32|windows/ end require "chef/config" require "mixlib/cli" +require "chef/dist" class Chef class Application @@ -40,23 +41,23 @@ class Chef short: "-a ACTION", long: "--action ACTION", default: "status", - description: "Action to carry out on chef-service (install, uninstall, status, start, stop, pause, or resume)" + description: "Action to carry out on chef-service (install, uninstall, status, start, stop, pause, or resume)." option :config_file, short: "-c CONFIG", long: "--config CONFIG", default: "#{ENV['SYSTEMDRIVE']}/chef/client.rb", - description: "The configuration file to use for chef runs" + description: "The configuration file to use for #{Chef::Dist::PRODUCT} runs." option :log_location, short: "-L LOGLOCATION", long: "--logfile LOGLOCATION", - description: "Set the log file location for chef-service" + description: "Set the log file location for chef-service." option :help, short: "-h", long: "--help", - description: "Show this message", + description: "Show this help message.", on: :tail, boolean: true, show_options: true, @@ -65,9 +66,9 @@ class Chef option :version, short: "-v", long: "--version", - description: "Show chef version", + description: "Show #{Chef::Dist::PRODUCT} version.", boolean: true, - proc: lambda { |v| puts "Chef: #{::Chef::VERSION}" }, + proc: lambda { |v| puts "#{Chef::Dist::PRODUCT}: #{::Chef::VERSION}" }, exit: 0 def initialize(service_options) diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb index 1294231e24..66853c58fb 100644 --- a/lib/chef/data_collector.rb +++ b/lib/chef/data_collector.rb @@ -26,6 +26,7 @@ require "chef/data_collector/run_end_message" require "chef/data_collector/run_start_message" require "chef/data_collector/config_validation" require "chef/data_collector/error_handlers" +require "chef/dist" class Chef class DataCollector @@ -303,7 +304,7 @@ class Chef return false when running_mode == :client && Chef::Config[:data_collector][:token] Chef::Log.warn("Data collector token authentication is not recommended for client-server mode. " \ - "Please upgrade Chef Server to 12.11.0 and remove the token from your config file " \ + "Please upgrade #{Chef::Dist::SERVER_PRODUCT} to 12.11 or later and remove the token from your config file " \ "to use key based authentication instead") return true when Chef::Config[:data_collector][:output_locations] && Chef::Config[:data_collector][:output_locations][:files] && !Chef::Config[:data_collector][:output_locations][:files].empty? @@ -311,7 +312,7 @@ class Chef return true when running_mode == :solo && !Chef::Config[:data_collector][:token] # we are in solo mode and are not logging to a file, so must have a token - Chef::Log.trace("Data collector token must be configured to use Chef Automate data collector with Chef Solo") + Chef::Log.trace("Data collector token must be configured to use Chef Automate data collector with #{Chef::Dist::PRODUCT} Solo") return false else return true diff --git a/lib/chef/dist.rb b/lib/chef/dist.rb index 51dd03e965..ed9307900b 100644 --- a/lib/chef/dist.rb +++ b/lib/chef/dist.rb @@ -2,7 +2,10 @@ class Chef class Dist # This class is not fully implemented, depending on it is not recommended! # When referencing a product directly, like Chef (Now Chef Infra) - PRODUCT = "Chef Infra".freeze + PRODUCT = "Chef Infra Client".freeze + + # The name of the server product + SERVER_PRODUCT = "Chef Infra Server".freeze # The client's alias (chef-client) CLIENT = "chef-client".freeze diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 0b0a589d56..1fdbb66b1b 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -1,5 +1,6 @@ require "chef/formatters/base" require "chef/config" +require "chef/dist" class Chef module Formatters @@ -40,7 +41,7 @@ class Chef end def run_start(version, run_status) - puts_line "Starting Chef Client, version #{version}" + puts_line "Starting #{Chef::Dist::PRODUCT}, version #{version}" puts_line "OpenSSL FIPS 140 mode enabled" if Chef::Config[:fips] end @@ -75,18 +76,18 @@ class Chef puts_line "" end if Chef::Config[:why_run] - puts_line "Chef Client finished, #{@updated_resources}/#{total_resources} resources would have been updated" + puts_line "#{Chef::Dist::PRODUCT} finished, #{@updated_resources}/#{total_resources} resources would have been updated" else - puts_line "Chef Client finished, #{@updated_resources}/#{total_resources} resources updated in #{pretty_elapsed_time}" + puts_line "#{Chef::Dist::PRODUCT} finished, #{@updated_resources}/#{total_resources} resources updated in #{pretty_elapsed_time}" end end def run_failed(exception) @end_time = Time.now if Chef::Config[:why_run] - puts_line "Chef Client failed. #{@updated_resources} resources would have been updated" + puts_line "#{Chef::Dist::PRODUCT} failed. #{@updated_resources} resources would have been updated" else - puts_line "Chef Client failed. #{@updated_resources} resources updated in #{pretty_elapsed_time}" + puts_line "#{Chef::Dist::PRODUCT} failed. #{@updated_resources} resources updated in #{pretty_elapsed_time}" end end diff --git a/lib/chef/formatters/error_inspectors/api_error_formatting.rb b/lib/chef/formatters/error_inspectors/api_error_formatting.rb index e74c353ba9..6dd6ed292f 100644 --- a/lib/chef/formatters/error_inspectors/api_error_formatting.rb +++ b/lib/chef/formatters/error_inspectors/api_error_formatting.rb @@ -112,10 +112,10 @@ class Chef max_server_version = version_header["max_version"] error_description.section("Incompatible server API version:", <<~E) - This version of the API that this Chef request specified is not supported by the Chef server you sent this request to. + This version of the API that this request specified is not supported by the server you sent this request to. The server supports a min API version of #{min_server_version} and a max API version of #{max_server_version}. - Chef just made a request with an API version of #{client_api_version}. - Please either update your Chef client or server to be a compatible set. + #{Chef::Dist::PRODUCT} just made a request with an API version of #{client_api_version}. + Please either update your #{Chef::Dist::PRODUCT} or the server to be a compatible set. E else describe_http_error(error_description) @@ -130,7 +130,7 @@ class Chef end def describe_503_error(error_description) - error_description.section("Server Unavailable", "The Chef Server is temporarily unavailable") + error_description.section("Server Unavailable", "The #{Chef::Dist::SERVER_PRODUCT} is temporarily unavailable") error_description.section("Server Response:", format_rest_error) end diff --git a/lib/chef/formatters/error_inspectors/registration_error_inspector.rb b/lib/chef/formatters/error_inspectors/registration_error_inspector.rb index 5ba5eba39d..7ab309be70 100644 --- a/lib/chef/formatters/error_inspectors/registration_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/registration_error_inspector.rb @@ -107,7 +107,7 @@ class Chef E error_description.section("Server Response:", format_rest_error) when Net::HTTPBadGateway, Net::HTTPServiceUnavailable - error_description.section("Server Unavailable", "The Chef Server is temporarily unavailable") + error_description.section("Server Unavailable", "The #{Chef::Dist::SERVER_PRODUCT} is temporarily unavailable") error_description.section("Server Response:", format_rest_error) else error_description.section("Unexpected API Request Failure:", format_rest_error) diff --git a/lib/chef/formatters/error_inspectors/run_list_expansion_error_inspector.rb b/lib/chef/formatters/error_inspectors/run_list_expansion_error_inspector.rb index 3efb1d4d45..d6fe3564f7 100644 --- a/lib/chef/formatters/error_inspectors/run_list_expansion_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/run_list_expansion_error_inspector.rb @@ -18,6 +18,7 @@ # require "chef/formatters/error_inspectors/api_error_formatting" +require "chef/dist" class Chef module Formatters @@ -77,7 +78,7 @@ class Chef case response when Net::HTTPUnauthorized error_description.section("Authentication Error:", <<~E) - Failed to authenticate to the chef server (http 401). + Failed to authenticate to the #{Chef::Dist::SERVER_PRODUCT} (http 401). E error_description.section("Server Response:", format_rest_error) @@ -108,7 +109,7 @@ class Chef E error_description.section("Server Response:", format_rest_error) when Net::HTTPBadGateway, Net::HTTPServiceUnavailable - error_description.section("Server Unavailable", "The Chef Server is temporarily unavailable") + error_description.section("Server Unavailable", "The #{Chef::Dist::SERVER_PRODUCT} is temporarily unavailable") error_description.section("Server Response:", format_rest_error) else error_description.section("Unexpected API Request Failure:", format_rest_error) diff --git a/lib/chef/formatters/minimal.rb b/lib/chef/formatters/minimal.rb index e182189f7d..6b12be71b7 100644 --- a/lib/chef/formatters/minimal.rb +++ b/lib/chef/formatters/minimal.rb @@ -1,4 +1,5 @@ require "chef/formatters/base" +require "chef/dist" class Chef @@ -27,18 +28,18 @@ class Chef # Called at the very start of a Chef Run def run_start(version, run_status) - puts_line "Starting Chef Client, version #{version}" + puts_line "Starting #{Chef::Dist::PRODUCT}, version #{version}" puts_line "OpenSSL FIPS 140 mode enabled" if Chef::Config[:fips] end # Called at the end of the Chef run. def run_completed(node) - puts "chef client finished, #{@updated_resources.size} resources updated" + puts "#{Chef::Dist::PRODUCT} finished, #{@updated_resources.size} resources updated" end # called at the end of a failed run def run_failed(exception) - puts "chef client failed. #{@updated_resources.size} resources updated" + puts "#{Chef::Dist::PRODUCT} failed. #{@updated_resources.size} resources updated" end # Called right after ohai runs. diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index aac0c8e258..da9c1ab1e9 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -474,7 +474,7 @@ class Chef when OpenSSL::SSL::SSLError ui.error "Could not establish a secure connection to the server." ui.info "Use `knife ssl check` to troubleshoot your SSL configuration." - ui.info "If your #{Chef::Dist::PRODUCT} Server uses a self-signed certificate, you can use" + ui.info "If your server uses a self-signed certificate, you can use" ui.info "`knife ssl fetch` to make knife trust the server's certificates." ui.info "" ui.info "Original Exception: #{e.class.name}: #{e.message}" @@ -507,7 +507,7 @@ class Chef ui.error "You authenticated successfully to #{server_url} as #{username} but you are not authorized for this action." proxy_env_vars = ENV.to_hash.keys.map(&:downcase) & %w{http_proxy https_proxy ftp_proxy socks_proxy no_proxy} unless proxy_env_vars.empty? - ui.error "There are proxy servers configured, your #{Chef::Dist::PRODUCT} server may need to be added to NO_PROXY." + ui.error "There are proxy servers configured, your server url may need to be added to NO_PROXY." end ui.info "Response: #{format_rest_error(response)}" when Net::HTTPBadRequest @@ -530,10 +530,10 @@ class Chef client_api_version = version_header["request_version"] min_server_version = version_header["min_version"] max_server_version = version_header["max_version"] - ui.error "The version of #{Chef::Dist::PRODUCT} that Knife is using is not supported by the #{Chef::Dist::PRODUCT} server you sent this request to" - ui.info "The request that Knife sent was using API version #{client_api_version}" - ui.info "The #{Chef::Dist::PRODUCT} server you sent the request to supports a min API verson of #{min_server_version} and a max API version of #{max_server_version}" - ui.info "Please either update your #{Chef::Dist::PRODUCT} client or server to be a compatible set" + ui.error "The API version that Knife is using is not supported by the server you sent this request to." + ui.info "The request that Knife sent was using API version #{client_api_version}." + ui.info "The server you sent the request to supports a min API verson of #{min_server_version} and a max API version of #{max_server_version}." + ui.info "Please either update your #{Chef::Dist::PRODUCT} or the server to be a compatible set." else ui.error response.message ui.info "Response: #{format_rest_error(response)}" diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index e879c2e822..69d9ffb8c0 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -18,6 +18,7 @@ require "chef/knife" require "chef/knife/data_bag_secret_options" +require "chef/dist" class Chef class Knife @@ -27,16 +28,25 @@ class Chef SUPPORTED_CONNECTION_PROTOCOLS = %w{ssh winrm}.freeze WINRM_AUTH_PROTOCOL_LIST = %w{plaintext kerberos ssl negotiate}.freeze + # @param opt_arry [Array] + # + # @return [String] a friendly quoted list of items complete with "and" + def self.friendly_opt_list(opt_array) + opts = opt_array.map { |x| "'#{x}'" } + return opts.join(" and ") if opts.size < 3 + opts[0..-2].join(", ") + " and " + opts[-1] + end + # Common connectivity options option :connection_user, short: "-U USERNAME", long: "--connection-user USERNAME", - description: "Authenticate to the target host with this user account" + description: "Authenticate to the target host with this user account." option :connection_password, short: "-P PASSWORD", long: "--connection-password PASSWORD", - description: "Authenticate to the target host with this password" + description: "Authenticate to the target host with this password." option :connection_port, short: "-p PORT", @@ -46,7 +56,7 @@ class Chef option :connection_protocol, short: "-o PROTOCOL", long: "--connection-protocol PROTOCOL", - description: "The protocol to use to connect to the target node. Supports: #{SUPPORTED_CONNECTION_PROTOCOLS.join(" ")}" + description: "The protocol to use to connect to the target node. Supports: #{friendly_opt_list(SUPPORTED_CONNECTION_PROTOCOLS)}." option :max_wait, short: "-W SECONDS", @@ -61,7 +71,7 @@ class Chef option :ca_trust_file, short: "-f CA_TRUST_PATH", long: "--ca-trust-file CA_TRUST_PATH", - description: "The Certificate Authority (CA) trust file used for SSL transport" + description: "The Certificate Authority (CA) trust file used for SSL transport." option :winrm_no_verify_cert, long: "--winrm-no-verify-cert", @@ -70,17 +80,17 @@ class Chef option :winrm_ssl, long: "--winrm-ssl", - description: "Connect to WinRM using SSL" + description: "Use SSL in the WinRM connection." option :winrm_auth_method, short: "-w AUTH-METHOD", long: "--winrm-auth-method AUTH-METHOD", - description: "The WinRM authentication method to use. Valid choices are #{WINRM_AUTH_PROTOCOL_LIST}", + description: "The WinRM authentication method to use. Valid choices are #{friendly_opt_list(WINRM_AUTH_PROTOCOL_LIST)}.", proc: Proc.new { |protocol| Chef::Config[:knife][:winrm_auth_method] = protocol } option :winrm_basic_auth_only, long: "--winrm-basic-auth-only", - description: "For WinRM basic authentication when using the 'ssl' auth method", + description: "For WinRM basic authentication when using the 'ssl' auth method.", boolean: true # This option was provided in knife bootstrap windows winrm, @@ -94,42 +104,42 @@ class Chef option :kerberos_realm, short: "-R KERBEROS_REALM", long: "--kerberos-realm KERBEROS_REALM", - description: "The Kerberos realm used for authentication", + description: "The Kerberos realm used for authentication.", proc: Proc.new { |protocol| Chef::Config[:knife][:kerberos_realm] = protocol } option :kerberos_service, short: "-S KERBEROS_SERVICE", long: "--kerberos-service KERBEROS_SERVICE", - description: "The Kerberos service used for authentication", + description: "The Kerberos service used for authentication.", proc: Proc.new { |protocol| Chef::Config[:knife][:kerberos_service] = protocol } option :winrm_session_timeout, long: "--winrm-session-timeout SECONDS", - description: "The number of seconds to wait for each WinRM operation to be acknowledged while running bootstrap", + description: "The number of seconds to wait for each WinRM operation to be acknowledged while running bootstrap.", proc: Proc.new { |protocol| Chef::Config[:knife][:winrm_session_timeout] = protocol } ## SSH Authentication option :ssh_gateway, short: "-G GATEWAY", long: "--ssh-gateway GATEWAY", - description: "The ssh gateway", + description: "The SSH gateway.", proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key } option :ssh_gateway_identity, long: "--ssh-gateway-identity SSH_GATEWAY_IDENTITY", - description: "The SSH identity file used for gateway authentication", + description: "The SSH identity file used for gateway authentication.", proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key } option :ssh_forward_agent, short: "-A", long: "--ssh-forward-agent", - description: "Enable SSH agent forwarding", + description: "Enable SSH agent forwarding.", boolean: true option :ssh_identity_file, short: "-i IDENTITY_FILE", long: "--ssh-identity-file IDENTITY_FILE", - description: "The SSH identity file used for authentication" + description: "The SSH identity file used for authentication." option :ssh_verify_host_key, long: "--[no-]ssh-verify-host-key", @@ -143,36 +153,36 @@ class Chef # client.rb content via chef-full/bootstrap_context option :bootstrap_version, long: "--bootstrap-version VERSION", - description: "The version of Chef to install", + description: "The version of #{Chef::Dist::PRODUCT} to install.", proc: lambda { |v| Chef::Config[:knife][:bootstrap_version] = v } # 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", + description: "The proxy server for the node being bootstrapped.", proc: Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p } # client.rb content via bootstrap_context option :bootstrap_proxy_user, long: "--bootstrap-proxy-user PROXY_USER", - description: "The proxy authentication username for the node being bootstrapped" + description: "The proxy authentication username for the node being bootstrapped." # client.rb content via bootstrap_context option :bootstrap_proxy_pass, long: "--bootstrap-proxy-pass PROXY_PASS", - description: "The proxy authentication password for the node being bootstrapped" + description: "The proxy authentication password for the node being bootstrapped." # 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; this option is used internally by Chef", + description: "Do not proxy locations for the node being bootstrapped; this option is used internally by Chef.", proc: Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np } # client.rb content via bootstrap_context option :bootstrap_template, short: "-t TEMPLATE", long: "--bootstrap-template TEMPLATE", - description: "Bootstrap Chef using a built-in or custom template. Set to the full path of an erb template or use one of the built-in templates." + description: "Bootstrap #{Chef::Dist::PRODUCT} using a built-in or custom template. Set to the full path of an erb template or use one of the built-in templates." # client.rb content via bootstrap_context option :node_ssl_verify_mode, @@ -189,57 +199,57 @@ class Chef # bootstrap_context - client.rb option :node_verify_api_cert, long: "--[no-]node-verify-api-cert", - description: "Verify the SSL cert for HTTPS requests to the Chef server API.", + description: "Verify the SSL cert for HTTPS requests to the #{Chef::Dist::SERVER_PRODUCT} API.", boolean: true # runtime - sudo settings (train handles sudo) option :use_sudo, long: "--sudo", - description: "Execute the bootstrap via sudo", + description: "Execute the bootstrap via sudo.", boolean: true # runtime - sudo settings (train handles sudo) option :preserve_home, long: "--sudo-preserve-home", - description: "Preserve non-root user HOME environment variable with sudo", + description: "Preserve non-root user HOME environment variable with sudo.", boolean: true # runtime - sudo settings (train handles sudo) option :use_sudo_password, long: "--use-sudo-password", - description: "Execute the bootstrap via sudo with password", + description: "Execute the bootstrap via sudo with password.", boolean: false # runtime - client_builder option :chef_node_name, short: "-N NAME", long: "--node-name NAME", - description: "The Chef node name for your new node" + description: "The node name for your new node." # runtime - client_builder - set runlist when creating node option :run_list, short: "-r RUN_LIST", long: "--run-list RUN_LIST", - description: "Comma separated list of roles/recipes to apply", + description: "Comma separated list of roles/recipes to apply.", proc: lambda { |o| o.split(/[\s,]+/) }, default: [] # runtime - client_builder - set policy name when creating node option :policy_name, long: "--policy-name POLICY_NAME", - description: "Policyfile name to use (--policy-group must also be given)", + description: "Policyfile name to use (--policy-group must also be given).", default: nil # runtime - client_builder - set policy group when creating node option :policy_group, long: "--policy-group POLICY_GROUP", - description: "Policy group name to use (--policy-name must also be given)", + description: "Policy group name to use (--policy-name must also be given).", default: nil # runtime - client_builder - node tags option :tags, long: "--tags TAGS", - description: "Comma separated list of tags to apply to the node", + description: "Comma separated list of tags to apply to the node.", proc: lambda { |o| o.split(/[\s,]+/) }, default: [] @@ -247,14 +257,14 @@ class Chef option :first_boot_attributes, short: "-j JSON_ATTRIBS", long: "--json-attributes", - description: "A JSON string to be added to the first run of #{Chef::Dist::CLIENT}", + description: "A JSON string to be added to the first run of #{Chef::Dist::CLIENT}.", proc: lambda { |o| Chef::JSONCompat.parse(o) }, default: nil # bootstrap template option :first_boot_attributes_from_file, long: "--json-attribute-file FILE", - description: "A JSON file to be used to the first run of #{Chef::Dist::CLIENT}", + description: "A JSON file to be used to the first run of #{Chef::Dist::CLIENT}.", proc: lambda { |o| Chef::JSONCompat.parse(File.read(o)) }, default: nil @@ -268,7 +278,7 @@ class Chef # Create ohai hints in /etc/chef/ohai/hints, fname=hintname, content=value option :hint, long: "--hint HINT_NAME[=HINT_FILE]", - description: "Specify Ohai Hint to be set on the bootstrap target. Use multiple --hint options to specify multiple hints.", + 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] ||= Hash.new name, path = h.split("=") @@ -280,53 +290,53 @@ 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", + description: "URL to a custom installation script.", proc: Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u } option :msi_url, # Windows target only short: "-m URL", long: "--msi-url URL", - description: "Location of the Chef Client MSI. The default templates will prefer to download from this location. The MSI will be downloaded from chef.io if not provided (windows).", + description: "Location of the #{Chef::Dist::PRODUCT} MSI. The default templates will prefer to download from this location. The MSI will be downloaded from #{Chef::Dist::WEBSITE} if not provided (Windows).", default: "" # 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::CLIENT}", + description: "Custom command to install #{Chef::Dist::PRODUCT}.", proc: Proc.new { |ic| Chef::Config[:knife][:bootstrap_install_command] = ic } # 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::CLIENT}", + description: "Custom commands to run before installing #{Chef::Dist::PRODUCT}.", proc: Proc.new { |preic| Chef::Config[:knife][:bootstrap_preinstall_command] = preic } # bootstrap template option :bootstrap_wget_options, long: "--bootstrap-wget-options OPTIONS", - description: "Add options to wget when installing #{Chef::Dist::CLIENT}", + description: "Add options to wget when installing #{Chef::Dist::PRODUCT}.", proc: Proc.new { |wo| Chef::Config[:knife][:bootstrap_wget_options] = wo } # bootstrap template option :bootstrap_curl_options, long: "--bootstrap-curl-options OPTIONS", - description: "Add options to curl when install #{Chef::Dist::CLIENT}", + description: "Add options to curl when install #{Chef::Dist::PRODUCT}.", proc: Proc.new { |co| Chef::Config[:knife][:bootstrap_curl_options] = co } # chef_vault_handler option :bootstrap_vault_file, long: "--bootstrap-vault-file VAULT_FILE", - description: "A JSON file with a list of vault(s) and item(s) to be updated" + description: "A JSON file with a list of vault(s) and item(s) to be updated." # chef_vault_handler option :bootstrap_vault_json, long: "--bootstrap-vault-json VAULT_JSON", - description: "A JSON string with the vault(s) and item(s) to be updated" + description: "A JSON string with the vault(s) and item(s) to be updated." # chef_vault_handler option :bootstrap_vault_item, long: "--bootstrap-vault-item VAULT_ITEM", - description: 'A single vault and item to update as "vault:item"', + description: 'A single vault and item to update as "vault:item".', proc: Proc.new { |i| (vault, item) = i.split(/:/) Chef::Config[:knife][:bootstrap_vault_item] ||= {} @@ -537,8 +547,8 @@ class Chef chef_vault_handler.run(client_builder.client) else ui.info <<~EOM - Doing old-style registration with the validation key at #{Chef::Config[:validation_key]}..." - Delete your validation key in order to use your user credentials instead + Performing legacy client registration with the validation key at #{Chef::Config[:validation_key]}..." + Delete your validation key in order to use your user credentials for client registration instead. EOM end @@ -562,6 +572,7 @@ class Chef opts = connection_opts.dup do_connect(opts) rescue Train::Error => e + require "net/ssh" if e.cause && e.cause.class == Net::SSH::AuthenticationFailed if connection.password_auth? raise @@ -578,7 +589,6 @@ class Chef end end - # TODO - maybe remove the footgun detection this was built on. # url values override CLI flags, if you provide both # we'll use the one that you gave in the URL. def connection_protocol @@ -795,6 +805,7 @@ class Chef def ssh_opts opts = {} return opts if connection_protocol == "winrm" + opts[:non_interactive] = true # Prevent password prompts from underlying net/ssh opts[:forward_agent] = (config_value(:ssh_forward_agent) === true) opts end diff --git a/lib/chef/knife/bootstrap/train_connector.rb b/lib/chef/knife/bootstrap/train_connector.rb index 5230d6638c..df94290dbf 100644 --- a/lib/chef/knife/bootstrap/train_connector.rb +++ b/lib/chef/knife/bootstrap/train_connector.rb @@ -35,80 +35,85 @@ class Chef MKTEMP_NIX_COMMAND = "bash -c 'd=$(mktemp -d ${TMPDIR:-/tmp}/chef_XXXXXX); echo $d'".freeze - def initialize(host_url, default_transport, opts) - uri_opts = opts_from_uri(host_url) - uri_opts[:backend] ||= @default_transport - @transport_type = uri_opts[:backend] + def initialize(host_url, default_protocol, opts) + @host_url = host_url + @default_protocol = default_protocol + @opts_in = opts + end - # opts in the URI will override user-provided options - @config = transport_config(host_url, opts.merge(uri_opts)) + def config + @config ||= begin + uri_opts = opts_from_uri(@host_url, @default_protocol) + transport_config(@host_url, @opts_in.merge(uri_opts)) + end end - # Because creating a valid train connection for testing is a two-step process in which - # we need to connect before mocking config, - # we expose test_instance as a way for tests to create actual instances - # but ensure that they don't connect to any back end. - def self.test_instance(url, protocol: "ssh", - family: "unknown", name: "unknown", - release: "unknown", arch: "x86_64", - opts: {}) - # Specifying sudo: false ensures that attempted operations - # don't fail because the mock platform doesn't support sudo - tc = TrainConnector.new(url, protocol, { sudo: false }.merge(opts)) - tc.connect! - tc.connection.mock_os( - family: family, - name: name, - release: release, - arch: arch - ) - tc + def connection + @connection ||= begin + Train.validate_backend(config) + train = Train.create(config[:backend], config) + # Note that the train connection is not currently connected + # to the remote host, but it's ready to go. + train.connection + end end + # + # Establish a connection to the configured host. + # + # @raise [TrainError] + # @raise [TrainUserError] + # + # @return [TrueClass] true if the connection could be established. def connect! # Force connection to establish connection.wait_until_ready true end + # + # @return [String] the configured hostname def hostname - @config[:host] + config[:host] end + # Answers the question, "is this connection configured for password auth?" + # @return [Boolean] true if the connection is configured with password auth def password_auth? - @config.key? :password + config.key? :password end - # True if we're connected to a linux host + # Answers the question, "Am I connected to a linux host?" + # + # @return [Boolean] true if the connected host is linux. def linux? connection.platform.linux? end - # True if we're connected to a unix host. - # NOTE: this is always true - # for a linux host because train classifies - # linux as a unix + # Answers the question, "Am I connected to a unix host?" + # + # @note this will alwys return true for a linux host + # because train classifies linux as a unix + # + # @return [Boolean] true if the connected host is unix or linux def unix? connection.platform.unix? end - # True if we're connected to a windows host + # + # Answers the question, "Am I connected to a Windows host?" + # + # @return [Boolean] true if the connected host is Windows def windows? connection.platform.windows? end - def winrm? - @transport_type == "winrm" - end - - def ssh? - @transport_type == "ssh" - end - + # # Creates a temporary directory on the remote host if it - # hasn't already. Caches directory location. + # hasn't already. Caches directory location. For *nix, + # it will ensure that the directory is owned by the logged-in user # - # Returns the path on the remote host. + # @return [String] the temporary path created on the remote host. def temp_dir cmd = windows? ? MKTEMP_WIN_COMMAND : MKTEMP_NIX_COMMAND @tmpdir ||= begin @@ -119,43 +124,87 @@ class Chef # running with sudo right now - so this directory would be owned by root. # File upload is performed over SCP as the current logged-in user, # so we'll set ownership to ensure that works. - run_command!("chown #{@config[:user]} '#{dir}'") + run_command!("chown #{config[:user]} '#{dir}'") end dir end end + # + # Uploads a file from "local_path" to "remote_path" + # + # @param local_path [String] The path to a file on the local file system + # @param remote_path [String] The destination path on the remote file system. + # @return NilClass def upload_file!(local_path, remote_path) connection.upload(local_path, remote_path) + nil end + # + # Uploads the provided content into the file "remote_path" on the remote host. + # + # @param content [String] The content to upload into remote_path + # @param remote_path [String] The destination path on the remote file system. + # @return NilClass def upload_file_content!(content, remote_path) t = Tempfile.new("chef-content") t << content t.close upload_file!(t.path, remote_path) + nil ensure t.close t.unlink end + # + # Force-deletes the file at "path" from the remote host. + # + # @param path [String] The path of the file on the remote host def del_file!(path) if windows? run_command!("If (Test-Path \"#{path}\") { Remove-Item -Force -Path \"#{path}\" }") else run_command!("rm -f \"#{path}\"") end + nil end - # normalizes path across OS's + # + # normalizes path across OS's - always use forward slashes, which + # Windows and *nix understand. + # + # @param path [String] The path to normalize + # + # @return [String] the normalized path def normalize_path(path) path.tr("\\", "/") end + # + # Runs a command on the remote host. + # + # @param command [String] The command to run. + # @param data_handler [Proc] An optional block. When provided, inbound data will be + # published via `data_handler.call(data)`. This can allow + # callers to receive and render updates from remote command execution. + # + # @return [Train::Extras::CommandResult] an object containing stdout, stderr, and exit_status def run_command(command, &data_handler) connection.run_command(command, &data_handler) end + # + # Runs a command the remote host + # + # @param command [String] The command to run. + # @param data_handler [Proc] An optional block. When provided, inbound data will be + # published via `data_handler.call(data)`. This can allow + # callers to receive and render updates from remote command execution. + # + # @raise Chef::Knife::Bootstrap::RemoteExecutionFailed if an error occurs (non-zero exit status) + # @return [Train::Extras::CommandResult] an object containing stdout, stderr, and exit_status def run_command!(command, &data_handler) result = run_command(command, &data_handler) if result.exit_status != 0 @@ -164,37 +213,28 @@ class Chef result end - def connection - @connection ||= begin - Train.validate_backend(@config) - train = Train.create(@transport_type, @config) - train.connection - end - end - private # For a given url and set of options, create a config # hash suitable for passing into train. def transport_config(host_url, opts_in) + # These baseline opts are not protocol-specific opts = { target: host_url, - sudo: opts_in[:sudo] === false ? false : true, www_form_encoded_password: true, - key_files: opts_in[:key_files], - non_interactive: true, # Prevent password prompts transport_retries: 2, transport_retry_sleep: 1, - logger: opts_in[:logger], - backend: @transport_type } + backend: opts_in[:backend], + logger: opts_in[:logger] } - # Base opts are those provided by the caller directly + # Accepts options provided by caller if they're not already configured, + # but note that they will be constrained to valid options for the backend protocol opts.merge!(opts_from_caller(opts, opts_in)) # WinRM has some additional computed options opts.merge!(opts_inferred_from_winrm(opts, opts_in)) - # Now that everything is populated, fill in anything left - # from user ssh config that may be present + # Now that everything is populated, fill in anything missing + # that may be found in user ssh config opts.merge!(missing_opts_from_ssh_config(opts, opts_in)) Train.target_config(opts) @@ -203,7 +243,7 @@ class Chef # Some winrm options are inferred based on other options. # Return a hash of winrm options based on configuration already built. def opts_inferred_from_winrm(config, opts_in) - return {} unless winrm? + return {} unless config[:backend] == "winrm" opts_out = {} if opts_in[:ssl] @@ -233,14 +273,14 @@ class Chef # Extract any of username/password/host/port/transport # that are in the URI and return them as a config has - def opts_from_uri(uri) + def opts_from_uri(uri, default_protocol) # Train.unpack_target_from_uri only works for complete URIs in # form of proto://[user[:pass]@]host[:port]/ # So we'll add the protocol prefix if it's not supplied. uri_to_check = if URI.regexp.match(uri) uri else - "#{@transport_type}://#{uri}" + "#{default_protocol}://#{uri}" end Train.unpack_target_from_uri(uri_to_check) @@ -252,7 +292,7 @@ class Chef # This is necessary because train will default these values # itself - causing SSH config data to be ignored def missing_opts_from_ssh_config(config, opts_in) - return {} unless ssh? + return {} unless config[:backend] == "ssh" host_cfg = ssh_config_for_host(config[:host]) opts_out = {} opts_in.each do |key, _value| diff --git a/lib/chef/knife/client_bulk_delete.rb b/lib/chef/knife/client_bulk_delete.rb index 8bb7181d65..a4777a4a16 100644 --- a/lib/chef/knife/client_bulk_delete.rb +++ b/lib/chef/knife/client_bulk_delete.rb @@ -29,7 +29,7 @@ class Chef option :delete_validators, short: "-D", long: "--delete-validators", - description: "Force deletion of clients if they're validators" + description: "Force deletion of clients if they're validators." banner "knife client bulk delete REGEX (options)" diff --git a/lib/chef/knife/client_create.rb b/lib/chef/knife/client_create.rb index 62c8ff8417..869e174453 100644 --- a/lib/chef/knife/client_create.rb +++ b/lib/chef/knife/client_create.rb @@ -17,6 +17,7 @@ # require "chef/knife" +require "chef/dist" class Chef class Knife @@ -50,7 +51,7 @@ class Chef option :prevent_keygen, short: "-k", long: "--prevent-keygen", - description: "API V1 (Chef Server 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --public-key.", + description: "API V1 (#{Chef::Dist::SERVER_PRODUCT} 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --public-key.", boolean: true banner "knife client create CLIENTNAME (options)" diff --git a/lib/chef/knife/client_delete.rb b/lib/chef/knife/client_delete.rb index 7b09a9a351..b2e34352a2 100644 --- a/lib/chef/knife/client_delete.rb +++ b/lib/chef/knife/client_delete.rb @@ -29,7 +29,7 @@ class Chef option :delete_validators, short: "-D", long: "--delete-validators", - description: "Force deletion of client if it's a validator" + description: "Force deletion of client if it's a validator." banner "knife client delete [CLIENT [CLIENT]] (options)" diff --git a/lib/chef/knife/client_list.rb b/lib/chef/knife/client_list.rb index bf68c46990..49d833353d 100644 --- a/lib/chef/knife/client_list.rb +++ b/lib/chef/knife/client_list.rb @@ -31,7 +31,7 @@ class Chef option :with_uri, short: "-w", long: "--with-uri", - description: "Show corresponding URIs" + description: "Show corresponding URIs." def run output(format_list_for_display(Chef::ApiClientV1.list)) diff --git a/lib/chef/knife/client_reregister.rb b/lib/chef/knife/client_reregister.rb index 28660f60c0..37ef259cad 100644 --- a/lib/chef/knife/client_reregister.rb +++ b/lib/chef/knife/client_reregister.rb @@ -31,7 +31,7 @@ class Chef option :file, short: "-f FILE", long: "--file FILE", - description: "Write the key to a file" + description: "Write the key to a file." def run @client_name = @name_args[0] diff --git a/lib/chef/knife/cookbook_download.rb b/lib/chef/knife/cookbook_download.rb index a321d217db..d5b1040e3e 100644 --- a/lib/chef/knife/cookbook_download.rb +++ b/lib/chef/knife/cookbook_download.rb @@ -35,19 +35,19 @@ class Chef option :latest, short: "-N", long: "--latest", - description: "The version of the cookbook to download", + description: "The version of the cookbook to download.", boolean: true option :download_directory, short: "-d DOWNLOAD_DIRECTORY", long: "--dir DOWNLOAD_DIRECTORY", - description: "The directory to download the cookbook into", + description: "The directory to download the cookbook into.", default: Dir.pwd option :force, short: "-f", long: "--force", - description: "Force download over the download directory if it exists" + description: "Force download over the download directory if it exists." # TODO: tim/cw: 5-23-2010: need to implement knife-side # specificity for downloads - need to implement --platform and diff --git a/lib/chef/knife/cookbook_list.rb b/lib/chef/knife/cookbook_list.rb index deb36baef4..c5a5bd5835 100644 --- a/lib/chef/knife/cookbook_list.rb +++ b/lib/chef/knife/cookbook_list.rb @@ -28,7 +28,7 @@ class Chef option :with_uri, short: "-w", long: "--with-uri", - description: "Show corresponding URIs" + description: "Show corresponding URIs." option :all_versions, short: "-a", diff --git a/lib/chef/knife/cookbook_metadata.rb b/lib/chef/knife/cookbook_metadata.rb index 8a9c57f1c3..2b25f505a0 100644 --- a/lib/chef/knife/cookbook_metadata.rb +++ b/lib/chef/knife/cookbook_metadata.rb @@ -32,13 +32,13 @@ class Chef option :cookbook_path, short: "-o PATH:PATH", long: "--cookbook-path PATH:PATH", - description: "A colon-separated path to look for cookbooks in", + description: "A colon-separated path to look for cookbooks in.", proc: lambda { |o| o.split(":") } option :all, short: "-a", long: "--all", - description: "Generate metadata for all cookbooks, rather than just a single cookbook" + description: "Generate metadata for all cookbooks, rather than just a single cookbook." def run config[:cookbook_path] ||= Chef::Config[:cookbook_path] diff --git a/lib/chef/knife/cookbook_show.rb b/lib/chef/knife/cookbook_show.rb index 46ed7a1aa6..d42c114556 100644 --- a/lib/chef/knife/cookbook_show.rb +++ b/lib/chef/knife/cookbook_show.rb @@ -33,22 +33,22 @@ class Chef option :fqdn, short: "-f FQDN", long: "--fqdn FQDN", - description: "The FQDN of the host to see the file for" + description: "The FQDN of the host to see the file for." option :platform, short: "-p PLATFORM", long: "--platform PLATFORM", - description: "The platform to see the file for" + description: "The platform to see the file for." option :platform_version, short: "-V VERSION", long: "--platform-version VERSION", - description: "The platform version to see the file for" + description: "The platform version to see the file for." option :with_uri, short: "-w", long: "--with-uri", - description: "Show corresponding URIs" + description: "Show corresponding URIs." def run cookbook_name, cookbook_version, segment, filename = @name_args diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb index 32ad6a13ae..dfd8eb8956 100644 --- a/lib/chef/knife/core/status_presenter.rb +++ b/lib/chef/knife/core/status_presenter.rb @@ -100,7 +100,14 @@ class Chef fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn] name = node["name"] || node.name - run_list = (node["run_list"]).to_s if config[:run_list] + if config[:run_list] + if config[:long_output] + run_list = node.run_list.map { |rl| "#{rl.type}[#{rl.name}]" } + else + run_list = node["run_list"] + end + end + line_parts = Array.new if node["ohai_time"] @@ -128,7 +135,7 @@ class Chef line_parts << fqdn if fqdn line_parts << ip if ip - line_parts << run_list if run_list + line_parts << run_list.to_s if run_list if node["platform"] platform = node["platform"].dup diff --git a/lib/chef/knife/core/windows_bootstrap_context.rb b/lib/chef/knife/core/windows_bootstrap_context.rb index b1204aeb09..6054743106 100644 --- a/lib/chef/knife/core/windows_bootstrap_context.rb +++ b/lib/chef/knife/core/windows_bootstrap_context.rb @@ -347,7 +347,7 @@ class Chef <<~EOH @set MSIERRORCODE=!ERRORLEVEL! @if ERRORLEVEL 1 ( - @echo WARNING: Failed to install Chef Client MSI package in remote context with status code !MSIERRORCODE!. + @echo WARNING: Failed to install #{Chef::Dist::PRODUCT} MSI package in remote context with status code !MSIERRORCODE!. @echo WARNING: This may be due to a defect in operating system update KB2918614: http://support.microsoft.com/kb/2918614 @set OLDLOGLOCATION="%CHEF_CLIENT_MSI_LOG_PATH%-fail.log" @move "%CHEF_CLIENT_MSI_LOG_PATH%" "!OLDLOGLOCATION!" > NUL @@ -356,26 +356,26 @@ class Chef @schtasks /create /f /sc once /st 00:00:00 /tn chefclientbootstraptask /ru SYSTEM /rl HIGHEST /tr \"cmd /c #{command} & sleep 2 & waitfor /s %computername% /si chefclientinstalldone\" @if ERRORLEVEL 1 ( - @echo ERROR: Failed to create Chef Client installation scheduled task with status code !ERRORLEVEL! > "&2" + @echo ERROR: Failed to create #{Chef::Dist::PRODUCT} installation scheduled task with status code !ERRORLEVEL! > "&2" ) else ( - @echo Successfully created scheduled task to install Chef Client. + @echo Successfully created scheduled task to install #{Chef::Dist::PRODUCT}. @schtasks /run /tn chefclientbootstraptask @if ERRORLEVEL 1 ( - @echo ERROR: Failed to execut Chef Client installation scheduled task with status code !ERRORLEVEL!. > "&2" + @echo ERROR: Failed to execut #{Chef::Dist::PRODUCT} installation scheduled task with status code !ERRORLEVEL!. > "&2" ) else ( - @echo Successfully started Chef Client installation scheduled task. + @echo Successfully started #{Chef::Dist::PRODUCT} installation scheduled task. @echo Waiting for installation to complete -- this may take a few minutes... waitfor chefclientinstalldone /t 600 if ERRORLEVEL 1 ( - @echo ERROR: Timed out waiting for Chef Client package to install + @echo ERROR: Timed out waiting for #{Chef::Dist::PRODUCT} package to install ) else ( - @echo Finished waiting for Chef Client package to install. + @echo Finished waiting for #{Chef::Dist::PRODUCT} package to install. ) @schtasks /delete /f /tn chefclientbootstraptask > NUL ) ) ) else ( - @echo Successfully installed Chef Client package. + @echo Successfully installed #{Chef::Dist::PRODUCT} package. ) EOH end diff --git a/lib/chef/knife/deps.rb b/lib/chef/knife/deps.rb index 4cb77eea46..8efa0d0b65 100644 --- a/lib/chef/knife/deps.rb +++ b/lib/chef/knife/deps.rb @@ -32,14 +32,16 @@ class Chef long: "--[no-]recurse", boolean: true, description: "List dependencies recursively (default: true). Only works with --tree." + option :tree, long: "--tree", boolean: true, description: "Show dependencies in a visual tree. May show duplicates." + option :remote, long: "--remote", boolean: true, - description: "List dependencies on the server instead of the local filesystem" + description: "List dependencies on the server instead of the local filesystem." attr_accessor :exit_code diff --git a/lib/chef/knife/diff.rb b/lib/chef/knife/diff.rb index aac42ed5c5..bd75d31194 100644 --- a/lib/chef/knife/diff.rb +++ b/lib/chef/knife/diff.rb @@ -45,12 +45,11 @@ class Chef option :diff_filter, long: "--diff-filter=[(A|D|M|T)...[*]]", - description: "Select only files that are Added (A), Deleted (D), Modified (M), or have their type (i.e. regular file, directory) changed (T). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if - there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected." + description: "Select only files that are Added (A), Deleted (D), Modified (M), or have their type (i.e. regular file, directory) changed (T). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected." option :cookbook_version, long: "--cookbook-version VERSION", - description: "Version of cookbook to download (if there are multiple versions and cookbook_versions is false)" + description: "Version of cookbook to download (if there are multiple versions and cookbook_versions is false)." def run if config[:name_only] diff --git a/lib/chef/knife/exec.rb b/lib/chef/knife/exec.rb index ed7101c0cc..63598923de 100644 --- a/lib/chef/knife/exec.rb +++ b/lib/chef/knife/exec.rb @@ -26,12 +26,12 @@ class Chef::Knife::Exec < Chef::Knife option :exec, short: "-E CODE", long: "--exec CODE", - description: "a string of Chef code to execute" + description: "A string of Chef code to execute." option :script_path, short: "-p PATH:PATH", long: "--script-path PATH:PATH", - description: "A colon-separated path to look for scripts in", + description: "A colon-separated path to look for scripts in.", proc: lambda { |o| o.split(":") } deps do diff --git a/lib/chef/knife/list.rb b/lib/chef/knife/list.rb index 03954dcf00..10018ff74c 100644 --- a/lib/chef/knife/list.rb +++ b/lib/chef/knife/list.rb @@ -31,33 +31,33 @@ class Chef option :recursive, short: "-R", boolean: true, - description: "List directories recursively" + description: "List directories recursively." option :bare_directories, short: "-d", boolean: true, - description: "When directories match the pattern, do not show the directories' children" + description: "When directories match the pattern, do not show the directories' children." option :local, long: "--local", boolean: true, - description: "List local directory instead of remote" + description: "List local directory instead of remote." option :flat, short: "-f", long: "--flat", boolean: true, - description: "Show a list of filenames rather than the prettified ls-like output normally produced" + description: "Show a list of filenames rather than the prettified ls-like output normally produced." option :one_column, short: "-1", boolean: true, - description: "Show only one column of results" + description: "Show only one column of results." option :trailing_slashes, short: "-p", boolean: true, - description: "Show trailing slashes after directories" + description: "Show trailing slashes after directories." attr_accessor :exit_code diff --git a/lib/chef/knife/node_edit.rb b/lib/chef/knife/node_edit.rb index 7551a8a7da..b97302a3da 100644 --- a/lib/chef/knife/node_edit.rb +++ b/lib/chef/knife/node_edit.rb @@ -35,7 +35,7 @@ class Chef short: "-a", long: "--all", boolean: true, - description: "Display all attributes when editing" + description: "Display all attributes when editing." def run if node_name.nil? diff --git a/lib/chef/knife/node_list.rb b/lib/chef/knife/node_list.rb index 4bc2c34508..651f30862d 100644 --- a/lib/chef/knife/node_list.rb +++ b/lib/chef/knife/node_list.rb @@ -32,7 +32,7 @@ class Chef option :with_uri, short: "-w", long: "--with-uri", - description: "Show corresponding URIs" + description: "Show corresponding URIs." def run env = Chef::Config[:environment] diff --git a/lib/chef/knife/node_run_list_add.rb b/lib/chef/knife/node_run_list_add.rb index 3fc28c041d..eed9343e0a 100644 --- a/lib/chef/knife/node_run_list_add.rb +++ b/lib/chef/knife/node_run_list_add.rb @@ -32,12 +32,12 @@ class Chef option :after, short: "-a ITEM", long: "--after ITEM", - description: "Place the ENTRY in the run list after ITEM" + description: "Place the ENTRY in the run list after ITEM." option :before, - short: "-b ITEM", - long: "--before ITEM", - description: "Place the ENTRY in the run list before ITEM" + short: "-b ITEM", + long: "--before ITEM", + description: "Place the ENTRY in the run list before ITEM." def run node = Chef::Node.load(@name_args[0]) diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb index 6a4a123ad8..2381ffbdbd 100644 --- a/lib/chef/knife/user_create.rb +++ b/lib/chef/knife/user_create.rb @@ -18,6 +18,7 @@ # require "chef/knife" +require "chef/dist" class Chef class Knife @@ -41,7 +42,7 @@ class Chef option :prevent_keygen, short: "-k", long: "--prevent-keygen", - description: "API V1 (Chef Server 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --user-key.", + description: "API V1 (#{Chef::Dist::SERVER_PRODUCT} 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --user-key.", boolean: true banner "knife user create USERNAME DISPLAY_NAME FIRST_NAME LAST_NAME EMAIL PASSWORD (options)" diff --git a/lib/chef/knife/user_reregister.rb b/lib/chef/knife/user_reregister.rb index 3c63c32f29..7530327131 100644 --- a/lib/chef/knife/user_reregister.rb +++ b/lib/chef/knife/user_reregister.rb @@ -31,7 +31,7 @@ class Chef option :file, short: "-f FILE", long: "--file FILE", - description: "Write the private key to a file" + description: "Write the private key to a file." def run @user_name = @name_args[0] diff --git a/lib/chef/knife/xargs.rb b/lib/chef/knife/xargs.rb index ae5851f465..603279bcdd 100644 --- a/lib/chef/knife/xargs.rb +++ b/lib/chef/knife/xargs.rb @@ -32,7 +32,7 @@ class Chef option :local, long: "--local", boolean: true, - description: "Xargs local files instead of remote" + description: "Xargs local files instead of remote." option :patterns, long: "--pattern [PATTERN]", diff --git a/lib/chef/run_lock.rb b/lib/chef/run_lock.rb index 513bfd8849..84b43afc19 100644 --- a/lib/chef/run_lock.rb +++ b/lib/chef/run_lock.rb @@ -96,7 +96,7 @@ class Chef # Waits until acquiring the system-wide lock. # def wait - Chef::Log.warn("#{Chef::Dist::PRODUCT} client #{runpid} is running, will wait for it to finish and then run.") + Chef::Log.warn("#{Chef::Dist::PRODUCT} #{runpid} is running, will wait for it to finish and then run.") if Chef::Platform.windows? mutex.wait else diff --git a/lib/chef/version.rb b/lib/chef/version.rb index c93c068caa..49a19d1014 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -23,7 +23,7 @@ require "chef/version_string" class Chef CHEF_ROOT = File.expand_path("../..", __FILE__) - VERSION = Chef::VersionString.new("15.0.253") + VERSION = Chef::VersionString.new("15.0.258") end # diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index a098256d36..3d2efe703c 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -163,7 +163,7 @@ describe "chef-solo" do ruby_block "sleeping" do block do retries = 200 - while IO.read(Chef::Config[:log_location]) !~ /.* client .* is running, will wait for it to finish and then run./ + while IO.read(Chef::Config[:log_location]) !~ /.* is running, will wait for it to finish and then run./ sleep 0.1 raise "we ran out of retries" if ( retries -= 1 ) <= 0 end @@ -207,7 +207,7 @@ describe "chef-solo" do run_log = File.read(path_to("logs/runs.log")) # second run should have a message which indicates it's waiting for the first run - expect(run_log).to match(/.* client .* is running, will wait for it to finish and then run./) + expect(run_log).to match(/.* is running, will wait for it to finish and then run./) # both of the runs should succeed expect(run_log.lines.reject { |l| !l.include? "Run complete in" }.length).to eq(2) diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index 8daba1d660..df1b6c99e2 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -326,7 +326,7 @@ describe Chef::Application::Client, "reconfigure" do Chef::Config[:interval] = 600 allow(ChefConfig).to receive(:windows?).and_return(false) expect(Chef::Application).to receive(:fatal!).with( - /Unforked .* interval runs are disabled in .* 12\. + /Unforked .* interval runs are disabled by default\. Configuration settings: interval = 600 seconds Enable .* interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options\./ diff --git a/spec/unit/application/exit_code_spec.rb b/spec/unit/application/exit_code_spec.rb index e8a0072ff3..6800ad0de5 100644 --- a/spec/unit/application/exit_code_spec.rb +++ b/spec/unit/application/exit_code_spec.rb @@ -70,7 +70,7 @@ describe Chef::Application::ExitCode do it "does write a warning on non-standard exit codes" do expect(Chef::Log).to receive(:warn).with( - /^Chef attempted to exit with a non-standard exit code of 151/) + /attempted to exit with a non-standard exit code of 151/) expect(exit_codes.normalize_exit_code(151)).to eq(1) end diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb index 1a4961f025..74f71a9115 100644 --- a/spec/unit/application/solo_spec.rb +++ b/spec/unit/application/solo_spec.rb @@ -64,7 +64,7 @@ describe Chef::Application::Solo do it "should terminate with message" do expect(Chef::Application).to receive(:fatal!).with( - /Unforked .* interval runs are disabled in .* 12\. + /Unforked .* interval runs are disabled by default\. Configuration settings: interval = 600 seconds Enable .* interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options\./ diff --git a/spec/unit/knife/bootstrap/train_connector_spec.rb b/spec/unit/knife/bootstrap/train_connector_spec.rb index 08bf21dd42..385a192648 100644 --- a/spec/unit/knife/bootstrap/train_connector_spec.rb +++ b/spec/unit/knife/bootstrap/train_connector_spec.rb @@ -25,20 +25,26 @@ describe Chef::Knife::Bootstrap::TrainConnector do let(:release) { "unknown" } # version let(:name) { "unknown" } let(:arch) { "x86_64" } + let(:connection_opts) { {} } # connection opts let(:host_url) { "mock://user1@example.com" } - let(:opts) { {} } + let(:mock_connection) { true } + subject do - # Create a valid TargetHost with the backend stubbed out. - Chef::Knife::Bootstrap::TrainConnector.test_instance(host_url, - protocol: protocol, - family: family, - name: name, - release: release, - arch: arch, - opts: opts) + # Example groups can still override by setting explicitly it in 'connection_opts' + tc = Chef::Knife::Bootstrap::TrainConnector.new(host_url, protocol, connection_opts) + tc end - context "connect!" do + before(:each) do + if mock_connection + subject.connect! + subject.connection.mock_os( + family: family, + name: name, + release: release, + arch: arch + ) + end end describe "platform helpers" do @@ -78,6 +84,61 @@ describe Chef::Knife::Bootstrap::TrainConnector do end end + describe "#initialize" do + let(:mock_connection) { false } + + context "when provided target is a proper URL" do + let(:protocol) { "ssh" } + let(:host_url) { "mock://user1@localhost:2200" } + it "correctly configures the instance from the URL" do + expect(subject.config[:backend]).to eq "mock" + expect(subject.config[:port]).to eq 2200 + expect(subject.config[:host]).to eq "localhost" + expect(subject.config[:user]).to eq "user1" + end + + context "and conflicting options are given" do + let(:connection_opts) { { user: "user2", host: "example.com", port: 15 } } + it "resolves them from the URI" do + expect(subject.config[:backend]).to eq "mock" + expect(subject.config[:port]).to eq 2200 + expect(subject.config[:host]).to eq "localhost" + expect(subject.config[:user]).to eq "user1" + end + end + end + + context "when provided target is just a hostname" do + let(:host_url) { "localhost" } + let(:protocol) { "mock" } + it "correctly sets backend protocol from the default" do + expect(subject.config[:backend]).to eq "mock" + end + + context "and options have been provided that are supported by the transport" do + let(:protocol) { "ssh" } + let(:connection_opts) { { port: 15, user: "user2" } } + + it "sets hostname and transport from arguments and provided fields from options" do + expect(subject.config[:backend]).to eq "ssh" + expect(subject.config[:host]).to eq "localhost" + expect(subject.config[:user]).to eq "user2" + expect(subject.config[:port]).to eq 15 + end + + end + + end + + context "when provided target is just a an IP address" do + let(:host_url) { "127.0.0.1" } + let(:protocol) { "mock" } + it "correctly sets backend protocol from the default" do + expect(subject.config[:backend]).to eq "mock" + end + end + end + describe "#temp_dir" do context "under windows" do let(:family) { "windows" } diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index 5bef9c5659..995a2ef4c9 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -961,6 +961,7 @@ describe Chef::Knife::Bootstrap do sudo: false, verify_host_key: false, port: 9999, + non_interactive: true, } end @@ -1012,6 +1013,7 @@ describe Chef::Knife::Bootstrap do sudo: true, # ccli verify_host_key: false, # Config port: 12, # cli + non_interactive: true, } end @@ -1060,6 +1062,7 @@ describe Chef::Knife::Bootstrap do sudo_options: "-H", sudo_password: "blah", verify_host_key: true, + non_interactive: true, } end it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do @@ -1079,6 +1082,7 @@ describe Chef::Knife::Bootstrap do keys_only: false, sudo: false, verify_host_key: true, + non_interactive: true, } end it "populates appropriate defaults" do @@ -1430,13 +1434,13 @@ describe Chef::Knife::Bootstrap do before do knife.config[:ssh_forward_agent] = true end - it "returns a configuration hash with forward_agent set to true" do - expect(knife.ssh_opts).to eq({ forward_agent: true }) + it "returns a configuration hash with forward_agent set to true. non-interactive is always true" do + expect(knife.ssh_opts).to eq({ forward_agent: true, non_interactive: true }) end end context "when ssh_forward_agent is not set" do - it "returns a configuration hash with forward_agent set to false" do - expect(knife.ssh_opts).to eq({ forward_agent: false }) + it "returns a configuration hash with forward_agent set to false. non-interactive is always true" do + expect(knife.ssh_opts).to eq({ forward_agent: false, non_interactive: true }) end end end diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb index f48ab4019c..7e05bec8f7 100644 --- a/spec/unit/knife_spec.rb +++ b/spec/unit/knife_spec.rb @@ -472,7 +472,7 @@ describe Chef::Knife do allow(knife).to receive(:username).and_return("sadpanda") knife.run_with_pretty_exceptions expect(stderr.string).to match(%r{ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action}) - expect(stderr.string).to match(%r{ERROR: There are proxy servers configured, your .* server may need to be added to NO_PROXY.}) + expect(stderr.string).to match(%r{ERROR: There are proxy servers configured, your server url may need to be added to NO_PROXY.}) expect(stderr.string).to match(%r{Response: y u no administrator}) end end @@ -508,9 +508,9 @@ describe Chef::Knife do allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("406 Not Acceptable", response)) knife.run_with_pretty_exceptions - expect(stderr.string).to match(/The request that .* sent was using API version 10000000/) - expect(stderr.string).to match(/The .* server you sent the request to supports a min API verson of 0 and a max API version of 1/) - expect(stderr.string).to match(/Please either update your .* client or server to be a compatible set/) + expect(stderr.string).to match(/The request that .* sent was using API version 10000000./) + expect(stderr.string).to match(/The server you sent the request to supports a min API verson of 0 and a max API version of 1./) + expect(stderr.string).to match(/Please either update your .* or the server to be a compatible set./) end it "formats 500s nicely" do @@ -588,7 +588,7 @@ describe Chef::Knife do expected_message = <<~MSG ERROR: Could not establish a secure connection to the server. Use `.* ssl check` to troubleshoot your SSL configuration. - If your .* Server uses a self-signed certificate, you can use + If your server uses a self-signed certificate, you can use `.* ssl fetch` to make .* trust the server's certificates. MSG expect(stderr.string).to match(expected_message) |