diff options
43 files changed, 453 insertions, 314 deletions
diff --git a/.expeditor/release.omnibus.yml b/.expeditor/release.omnibus.yml index 1819c0d207..700ecb108c 100644 --- a/.expeditor/release.omnibus.yml +++ b/.expeditor/release.omnibus.yml @@ -33,10 +33,10 @@ builder-to-testers-map: freebsd-11-amd64: - freebsd-11-amd64 - freebsd-12-amd64 - mac_os_x-10.12-x86_64: - - mac_os_x-10.12-x86_64 + mac_os_x-10.13-x86_64: - mac_os_x-10.13-x86_64 - mac_os_x-10.14-x86_64 + - mac_os_x-10.15-x86_64 sles-12-s390x: - sles-12-s390x sles-12-x86_64: diff --git a/.expeditor/verify.pipeline.yml b/.expeditor/verify.pipeline.yml index ef2ebb0b51..96b1e8e81d 100644 --- a/.expeditor/verify.pipeline.yml +++ b/.expeditor/verify.pipeline.yml @@ -2,6 +2,9 @@ expeditor: defaults: buildkite: + retry: + automatic: + limit: 1 timeout_in_minutes: 30 retry: automatic: @@ -189,6 +192,44 @@ steps: - FORCE_FFI_YAJL=ext - CHEF_LICENSE=accept-no-persist +- label: "Integration Specs Windows :ruby: 2.6" + commands: + - /workdir/scripts/bk_tests/bk_win_integration.ps1 + expeditor: + executor: + docker: + host_os: windows + os_version: 2016 + environment: + - FORCE_FFI_YAJL=ext + - CHEF_LICENSE=accept-no-persist + shell: ["powershell", "-Command"] + +- label: "Functional Specs Windows :ruby: 2.6" + commands: + - /workdir/scripts/bk_tests/bk_win_functional.ps1 + expeditor: + executor: + docker: + host_os: windows + os_version: 2016 + environment: + - FORCE_FFI_YAJL=ext + - CHEF_LICENSE=accept-no-persist + shell: ["powershell", "-Command"] + +- label: "Unit Specs Windows :ruby: 2.6" + commands: + - /workdir/scripts/bk_tests/bk_win_unit.ps1 + expeditor: + executor: + docker: + host_os: windows + environment: + - FORCE_FFI_YAJL=ext + - CHEF_LICENSE=accept-no-persist + shell: ["powershell", "-Command"] + - label: "Chefstyle :ruby: 2.6" commands: - /workdir/scripts/bk_tests/bk_container_prep.sh diff --git a/.rubocop.yml b/.rubocop.yml index c3eba7db55..9730861155 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -29,6 +29,3 @@ Lint/IneffectiveAccessModifier: Enabled: false Lint/ShadowedException: Enabled: false -Layout/AlignHash: - Enabled: true - EnforcedLastArgumentHashStyle: ignore_implicit diff --git a/CHANGELOG.md b/CHANGELOG.md index 355cac253f..77b32767b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,29 @@ <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ --> -<!-- latest_release 15.2.29 --> -## [v15.2.29](https://github.com/chef/chef/tree/v15.2.29) (2019-08-23) +<!-- latest_release 15.3.7 --> +## [v15.3.7](https://github.com/chef/chef/tree/v15.3.7) (2019-09-10) #### Merged Pull Requests -- ifconfig: fix regex matching interface name with hyphen [#8756](https://github.com/chef/chef/pull/8756) ([dheerajd-msys](https://github.com/dheerajd-msys)) +- Bootstrap: Set pty true only if required [#8816](https://github.com/chef/chef/pull/8816) ([vsingh-msys](https://github.com/vsingh-msys)) <!-- latest_release --> <!-- release_rollup since=15.2.20 --> ### Changes not yet released to stable #### Merged Pull Requests +- Bootstrap: Set pty true only if required [#8816](https://github.com/chef/chef/pull/8816) ([vsingh-msys](https://github.com/vsingh-msys)) <!-- 15.3.7 --> +- Add Chef 15.3 release notes [#8860](https://github.com/chef/chef/pull/8860) ([tas50](https://github.com/tas50)) <!-- 15.3.6 --> +- Remove duplicate policy_path config [#8864](https://github.com/chef/chef/pull/8864) ([tas50](https://github.com/tas50)) <!-- 15.3.5 --> +- convert chocolatey resource to use shell_out splat args [#8861](https://github.com/chef/chef/pull/8861) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.3.4 --> +- Migrate Appveyor windows testing to Buildkite [#8867](https://github.com/chef/chef/pull/8867) ([jaymalasinha](https://github.com/jaymalasinha)) <!-- 15.3.3 --> +- Bump ohai to 15.3.1 [#8863](https://github.com/chef/chef/pull/8863) ([chef-ci](https://github.com/chef-ci)) <!-- 15.3.2 --> +- Update libarchive to 3.4.0 and pin in omnibus_overrides.rb [#8862](https://github.com/chef/chef/pull/8862) ([tas50](https://github.com/tas50)) <!-- 15.3.1 --> +- Update InSpec to 4.16 and addressable to 2.7.0 [#8857](https://github.com/chef/chef/pull/8857) ([tas50](https://github.com/tas50)) <!-- 15.3.0 --> +- Deprecate macOS 10.12 and add macOS 10.15 support [#8850](https://github.com/chef/chef/pull/8850) ([jaymalasinha](https://github.com/jaymalasinha)) <!-- 15.2.35 --> +- Bootstrap: Only use sudo when changing ownership if --sudo is passed [#8815](https://github.com/chef/chef/pull/8815) ([vsingh-msys](https://github.com/vsingh-msys)) <!-- 15.2.34 --> +- Update InSpec to 4.12 and Train to 3.0 [#8854](https://github.com/chef/chef/pull/8854) ([tas50](https://github.com/tas50)) <!-- 15.2.33 --> +- remove app_server_support spec file [#8852](https://github.com/chef/chef/pull/8852) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.2.32 --> +- Fix node[:cookbooks] attribute [#8846](https://github.com/chef/chef/pull/8846) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.2.31 --> +- Fail on interval runs on windows as interval runs on Windows don't entirely work [#6777](https://github.com/chef/chef/pull/6777) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.2.30 --> - ifconfig: fix regex matching interface name with hyphen [#8756](https://github.com/chef/chef/pull/8756) ([dheerajd-msys](https://github.com/dheerajd-msys)) <!-- 15.2.29 --> - Add AIX 7.2 platform [#8832](https://github.com/chef/chef/pull/8832) ([jaymalasinha](https://github.com/jaymalasinha)) <!-- 15.2.28 --> - Fix crash when showing error about missing profile [#8828](https://github.com/chef/chef/pull/8828) ([andrewdotn](https://github.com/andrewdotn)) <!-- 15.2.27 --> diff --git a/Gemfile.lock b/Gemfile.lock index 03d5f16835..e0b729670a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,17 +1,17 @@ GIT remote: https://github.com/chef/chefstyle.git - revision: 56f2187784bf8b6840efc73adb2e35ef5f3862a7 + revision: 6c2d8583fd345c09c7931e2f8c0ed33a48925c40 branch: master specs: - chefstyle (0.13.2) + chefstyle (0.13.3) rubocop (= 0.72.0) GIT remote: https://github.com/chef/ohai.git - revision: f76c5f583736a5731e2fb6e92c21dc8419655d95 + revision: 9982b1e62ed1afb8db57349f536da3fed759749f branch: master specs: - ohai (15.2.5) + ohai (15.3.1) chef-config (>= 12.8, < 16) ffi (~> 1.9) ffi-yajl (~> 2.2) @@ -27,11 +27,11 @@ GIT PATH remote: . specs: - chef (15.2.29) + chef (15.3.7) addressable bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) - chef-config (= 15.2.29) + chef-config (= 15.3.7) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -46,7 +46,7 @@ PATH mixlib-authentication (~> 2.1) mixlib-cli (>= 2.1.1, < 3.0) mixlib-log (>= 2.0.3, < 4.0) - mixlib-shellout (>= 2.4, < 4.0) + mixlib-shellout (>= 3.0.3, < 4.0) net-sftp (~> 2.1, >= 2.1.2) net-ssh (>= 4.2, < 6) net-ssh-multi (~> 1.2, >= 1.2.1) @@ -54,14 +54,15 @@ PATH plist (~> 3.2) proxifier (~> 1.0) syslog-logger (~> 1.6) - train-core (~> 2.0, >= 2.0.12) + train-core (~> 3.0) + train-winrm tty-screen (~> 0.6) uuidtools (~> 2.1.5) - chef (15.2.29-universal-mingw32) + chef (15.3.7-universal-mingw32) addressable bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) - chef-config (= 15.2.29) + chef-config (= 15.3.7) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -77,7 +78,7 @@ PATH mixlib-authentication (~> 2.1) mixlib-cli (>= 2.1.1, < 3.0) mixlib-log (>= 2.0.3, < 4.0) - mixlib-shellout (>= 2.4, < 4.0) + mixlib-shellout (>= 3.0.3, < 4.0) net-sftp (~> 2.1, >= 2.1.2) net-ssh (>= 4.2, < 6) net-ssh-multi (~> 1.2, >= 1.2.1) @@ -85,7 +86,8 @@ PATH plist (~> 3.2) proxifier (~> 1.0) syslog-logger (~> 1.6) - train-core (~> 2.0, >= 2.0.12) + train-core (~> 3.0) + train-winrm tty-screen (~> 0.6) uuidtools (~> 2.1.5) win32-api (~> 1.5.3) @@ -103,13 +105,13 @@ PATH PATH remote: chef-bin specs: - chef-bin (15.2.29) - chef (= 15.2.29) + chef-bin (15.3.7) + chef (= 15.3.7) PATH remote: chef-config specs: - chef-config (15.2.29) + chef-config (15.3.7) addressable fuzzyurl mixlib-config (>= 2.2.12, < 4.0) @@ -119,8 +121,8 @@ PATH GEM remote: https://rubygems.org/ specs: - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) appbundler (0.13.1) mixlib-cli (>= 1.4, < 3.0) mixlib-shellout (>= 2.0, < 4.0) @@ -175,7 +177,7 @@ GEM htmlentities (4.3.4) httpclient (2.8.3) iniparse (1.4.4) - inspec-core (4.10.4) + inspec-core (4.16.0) addressable (~> 2.4) faraday (>= 0.9.0) faraday_middleware (~> 0.12.2) @@ -197,11 +199,11 @@ GEM term-ansicolor thor (~> 0.20) tomlrb (~> 1.2) - train-core (~> 2.0) + train-core (~> 3.0) tty-prompt (~> 0.17) tty-table (~> 0.10) - inspec-core-bin (4.10.4) - inspec-core (= 4.10.4) + inspec-core-bin (4.16.0) + inspec-core (= 4.16.0) ipaddress (0.8.3) iso8601 (0.12.1) jaro_winkler (1.5.3) @@ -247,7 +249,7 @@ GEM net-ssh-gateway (>= 1.2.0) nori (2.6.0) parallel (1.17.0) - parser (2.6.3.0) + parser (2.6.4.0) ast (~> 2.4.0) parslet (1.8.2) pastel (0.7.3) @@ -267,7 +269,7 @@ GEM pry-stack_explorer (0.4.9.3) binding_of_caller (>= 0.7) pry (>= 0.9.11) - public_suffix (3.1.1) + public_suffix (4.0.1) rack (2.0.7) rainbow (3.0.0) rake (12.3.2) @@ -312,12 +314,12 @@ GEM simplecov-html (0.10.2) slop (3.6.0) sslshake (1.3.0) - strings (0.1.5) + strings (0.1.6) strings-ansi (~> 0.1) unicode-display_width (~> 1.5) unicode_utils (~> 1.4) strings-ansi (0.1.0) - structured_warnings (0.3.0) + structured_warnings (0.4.0) syslog-logger (1.6.8) systemu (2.6.5) term-ansicolor (1.7.1) @@ -325,16 +327,17 @@ GEM thor (0.20.3) tins (1.21.1) tomlrb (1.2.8) - train-core (2.1.19) + train-core (3.0.3) json (>= 1.8, < 3.0) mixlib-shellout (>= 2.0, < 4.0) net-scp (>= 1.2, < 3.0) net-ssh (>= 2.9, < 6.0) + train-winrm (0.2.4) winrm (~> 2.0) winrm-fs (~> 1.0) - tty-box (0.4.0) + tty-box (0.4.1) pastel (~> 0.7.2) - strings (~> 0.1.5) + strings (~> 0.1.6) tty-cursor (~> 0.7) tty-color (0.5.0) tty-cursor (0.7.0) @@ -356,7 +359,7 @@ GEM unicode-display_width (1.6.0) unicode_utils (1.4.0) uuidtools (2.1.5) - webmock (3.6.2) + webmock (3.7.2) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -1,7 +1,6 @@ # Chef Infra [![Code Climate](https://codeclimate.com/github/chef/chef.svg)](https://codeclimate.com/github/chef/chef) [![Build Status](https://badge.buildkite.com/c82093430ceec7d27af05febb9dcafe3aa331fff9d74c0ab9d.svg?branch=master)](https://buildkite.com/chef-oss/chef-chef-master-verify) -[![Build Status Master](https://ci.appveyor.com/api/projects/status/github/chef/chef?branch=master&svg=true&passingText=master%20-%20Ok&pendingText=master%20-%20Pending&failingText=master%20-%20Failing)](https://ci.appveyor.com/project/Chef/chef/branch/master) [![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef) [![](https://img.shields.io/badge/Release%20Policy-Cadence%20Release-brightgreen.svg)](https://github.com/chef/chef/blob/v15.2.21/docs/dev/design_documents/client_release_cadence.md) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a13dc16420..182b735e31 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,64 @@ This file holds "in progress" release notes for the current release under development and is intended for consumption by the Chef Documentation team. Please see <https://docs.chef.io/release_notes.html> for the official Chef release notes. +# Chef Infra Client 15.3 + +## Custom Resource Unified Mode + +Chef Infra Client 15.3 introduces an exciting new way to easily write custom resources that mix built-in Chef Infra resources with Ruby code. Previously custom resources would use Chef Infra's standard compile and converge phases, which meant that Ruby would be evaluated first and then the resources would be converged. This often results in confusing and undesirable behavior when you are trying to mix resources with Ruby logic. Many custom resource authors would attempt to get around this by forcing resources to run at compile time so that all the code in their resource would execute during the compile phase. + +An example of forcing a resource to run at compile time: + +```ruby +resource_name 'foo' do + action :nothing +end.run_action(:some_action) +``` + +With unified mode, you opt in to a single phase per resource where all Ruby and Chef Infra resources are executed at once. This makes it far easier to determine how your code will be evaluated and run. Additionally, you no longer need to force any resources to run at compile time, as all code is run in the compile phase. To enable this new mode just add `unified_mode true` to your resources like this: + +```ruby +property :Some_property, String + +unified_mode true + +action :create do + # some code +end +``` + +## Interval Mode Now Fails on Windows + +Chef Infra Client 15.3 will now raise an error if you attempt to keep the chef-client process running long-term by enabling interval runs. Interval runs have already raised failures on non-Windows platforms and we've suggested that users move away from them on Windows for many years. The long-running chef-client process on Windows will load and reload cookbooks over each other in memory. This could produce a running state which is not a representation of the cookbook code that the authors wrote or tested, and behavior that may be wildly different depending on how long the chef-client process has been running and on the sequence that the cookbooks were uploaded. + +## Updated Resources + +### ifconfig + +The `ifconfig` resource has been updated to properly support interfaces with a hyphen in their name. This is most commonly encountered with bridge interfaces that are named `br-1234`. + +### archive_file + +The `archive_file` now supports archives in the RAR 5.0 format as well as zip files compressed using xz, lzma, ppmd8 and bzip2 compression. + +## Platform Support Updates + +### macOS 10.15 Support + +Chef Infra Client is now validated against macOS 10.15 (Catalina) with packages now available at [downloads.chef.io](https://downloads.chef.io/) and via the [Omnitruck API](https://docs.chef.io/api_omnitruck.html). Additionally, Chef Infra Client will no longer be validated against macOS 10.12. + +### AIX 7.2 + +Chef Infra Client is now validated against AIX 7.2 with packages now available at [downloads.chef.io](https://downloads.chef.io/) and via the [Omnitruck API](https://docs.chef.io/api_omnitruck.html). + +## Chef InSpec 4.16 + +Chef InSpec has been updated from 4.10.4 to 4.16.0 with the following changes: + +- A new `postfix_conf` has been added for inspecting Postfix configuration files. +- A new `plugins` section has been added to the InSpec configuration file which can be used to pass secrets or other configurations into Chef InSpec plugins. +- The `service` resource now includes a new `startname` property for determining which user is starting the Windows services. +- The `groups` resource now properly gathers membership information on macOS hosts. + # Chef Infra Client 15.2 ## Updated Resources @@ -1 +1 @@ -15.2.29
\ No newline at end of file +15.3.7
\ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index b7be639c1b..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,76 +0,0 @@ -version: "master-{build}" - -os: Visual Studio 2017 -platform: - - x64 - -cache: - - vendor/bundle - -configuration: - - integration - - functional - - unit - -environment: - matrix: - - ruby_version: "25-x64" - - ruby_version: "26-x64" - -clone_folder: c:\projects\chef -clone_depth: 1 - -skip_commits: - # version bumps by Expeditor happen as a separate commit after the merge, we can skip - message: /Bump version to [0-9.]+ by Chef Expeditor/ - # if ONLY the files listed below are changed in a commit, skip - files: - - CHANGELOG.md - - RELEASE_NOTES.md - -skip_tags: true -branches: - only: - - master - - chef-14 - -install: - - systeminfo - - winrm quickconfig -q - - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% - - echo %PATH% - - appveyor DownloadFile http://curl.haxx.se/ca/cacert.pem -FileName C:\cacert.pem - - set SSL_CERT_FILE=C:\cacert.pem - - bundle config --local path vendor/bundle # use the cache we define above - - bundle install --jobs=3 --retry=3 --without omnibus_package docgen chefstyle - - SET SPEC_OPTS=--format progress - - SET CHEF_LICENSE="accept-no-persist" - -build: off - -before_test: - - ruby --version - - gem --version - - bundler --version - - bundle env - -for: - - - matrix: - only: - - configuration: integration - build_script: - - bundle exec rake spec:integration - - - matrix: - only: - - configuration: functional - build_script: - - bundle exec rake spec:functional - - - matrix: - only: - - configuration: unit - build_script: - - bundle exec rake spec:unit - - bundle exec rake component_specs diff --git a/chef-bin/lib/chef-bin/version.rb b/chef-bin/lib/chef-bin/version.rb index c1481dcec4..3335dae144 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.2.29".freeze + VERSION = "15.3.7".freeze end # diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index b0583b7a06..0bb9ca4124 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -265,10 +265,6 @@ module ChefConfig # Defaults to <chef_repo_path>/users. default(:user_path) { derive_path_from_chef_repo_path("users") } - # Location of policies on disk. String or array of strings. - # Defaults to <chef_repo_path>/policies. - default(:policy_path) { derive_path_from_chef_repo_path("policies") } - # Turn on "path sanity" by default. default :enforce_path_sanity, false diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index c9a9ba2006..f9ac7f45b9 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.2.29".freeze + VERSION = "15.3.7".freeze end # diff --git a/chef.gemspec b/chef.gemspec index a89cf4ceb2..5d35bc2119 100644 --- a/chef.gemspec +++ b/chef.gemspec @@ -16,13 +16,14 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.5.0" s.add_dependency "chef-config", "= #{Chef::VERSION}" - s.add_dependency "train-core", "~> 2.0", ">= 2.0.12" + s.add_dependency "train-core", "~> 3.0" + s.add_dependency "train-winrm" s.add_dependency "license-acceptance", "~> 1.0", ">= 1.0.5" s.add_dependency "mixlib-cli", ">= 2.1.1", "< 3.0" s.add_dependency "mixlib-log", ">= 2.0.3", "< 4.0" s.add_dependency "mixlib-authentication", "~> 2.1" - s.add_dependency "mixlib-shellout", ">= 2.4", "< 4.0" + s.add_dependency "mixlib-shellout", ">= 3.0.3", "< 4.0" s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0" s.add_dependency "ohai", "~> 15.0" diff --git a/lib/chef/application/base.rb b/lib/chef/application/base.rb index fea3d844ce..c5bff9874e 100644 --- a/lib/chef/application/base.rb +++ b/lib/chef/application/base.rb @@ -340,6 +340,13 @@ class Chef::Application::Base < Chef::Application private + def windows_interval_error_message + "Windows #{Chef::Dist::PRODUCT} interval runs are not supported in #{Chef::Dist::PRODUCT} 15 and later." + + "\nConfiguration settings:" + + ("\n interval = #{Chef::Config[:interval]} seconds" if Chef::Config[:interval]).to_s + + "\nPlease manage #{Chef::Dist::PRODUCT} as a scheduled task instead." + end + def unforked_interval_error_message "Unforked #{Chef::Dist::PRODUCT} interval runs are disabled by default." + "\nConfiguration settings:" + diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index 0fc5ca7711..890ecbd385 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -128,8 +128,12 @@ class Chef::Application::Client < Chef::Application::Base Chef::Config[:client_fork] = !!Chef::Config[:interval] end - if !Chef::Config[:client_fork] && Chef::Config[:interval] && !Chef::Platform.windows? - Chef::Application.fatal!(unforked_interval_error_message) + if Chef::Config[:interval] + if Chef::Platform.windows? + Chef::Application.fatal!(windows_interval_error_message) + elsif !Chef::Config[:client_fork] + Chef::Application.fatal!(unforked_interval_error_message) + end end if Chef::Config[:json_attribs] diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index bce95c2841..da9ec7f566 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -102,7 +102,13 @@ class Chef::Application::Solo < Chef::Application::Base Chef::Config[:client_fork] = !!Chef::Config[:interval] end - Chef::Application.fatal!(unforked_interval_error_message) if !Chef::Config[:client_fork] && Chef::Config[:interval] + if Chef::Config[:interval] + if Chef::Platform.windows? + Chef::Application.fatal!(windows_interval_error_message) + elsif !Chef::Config[:client_fork] + Chef::Application.fatal!(unforked_interval_error_message) + end + end if Chef::Config[:recipe_url] cookbooks_path = Array(Chef::Config[:cookbook_path]).detect { |e| Pathname.new(e).cleanpath.to_s =~ %r{/cookbooks/*$} } diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index e892f1f2c9..efa1515858 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -672,6 +672,14 @@ class Chef def do_connect(conn_options) @connection = TrainConnector.new(host_descriptor, connection_protocol, conn_options) connection.connect! + rescue Train::UserError => e + if !conn_options.key?(:pty) && e.reason == :sudo_no_tty + ui.warn("#{e.message} - trying with pty request") + conn_options[:pty] = true # ensure we can talk to systems with requiretty set true in sshd config + retry + else + raise + end end # Fail if both first_boot_attributes and first_boot_attributes_from_file @@ -895,7 +903,6 @@ class Chef opts = {} return opts if winrm? - opts[:pty] = true # ensure we can talk to systems with requiretty set true in sshd config opts[:non_interactive] = true # Prevent password prompts from underlying net/ssh opts[:forward_agent] = (config_value(:ssh_forward_agent) === true) opts[:connection_timeout] = session_timeout diff --git a/lib/chef/knife/bootstrap/train_connector.rb b/lib/chef/knife/bootstrap/train_connector.rb index a3611470d1..66cde6f6b9 100644 --- a/lib/chef/knife/bootstrap/train_connector.rb +++ b/lib/chef/knife/bootstrap/train_connector.rb @@ -123,13 +123,13 @@ class Chef # eg. /tmp/chef_XXXXXX. # Use mkdir to create TEMP dir to get rid of mktemp dir = "#{DEFAULT_REMOTE_TEMP}/chef_#{SecureRandom.alphanumeric(6)}" - cmd = "mkdir -p %s" % dir + run_command!("mkdir -p '#{dir}'") # Ensure that dir has the correct owner. We are possibly # 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. - cmd += " && sudo chown #{config[:user]} '#{dir}'" - run_command!(cmd) + run_command!("chown #{config[:user]} '#{dir}'") if config[:sudo] + dir end end diff --git a/lib/chef/node.rb b/lib/chef/node.rb index ec20fbee86..1e5d3a8d59 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -87,8 +87,6 @@ class Chef # after the run_context has been set on the node, go through the cookbook_collection # and setup the node[:cookbooks] attribute so that it is published in the node object def set_cookbook_attribute - return unless run_context.cookbook_collection - run_context.cookbook_collection.each do |cookbook_name, cookbook| automatic_attrs[:cookbooks][cookbook_name][:version] = cookbook.version end diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb index 4afb4d7d60..bb5e2e199b 100644 --- a/lib/chef/policy_builder/expand_node_object.rb +++ b/lib/chef/policy_builder/expand_node_object.rb @@ -75,7 +75,6 @@ class Chef # def setup_run_context(specific_recipes = nil, run_context = nil) run_context ||= Chef::RunContext.new - run_context.events = events run_context.node = node @@ -93,6 +92,7 @@ class Chef cookbook_collection.validate! cookbook_collection.install_gems(events) + run_context.cookbook_collection = cookbook_collection # TODO: move this into the cookbook_compilation_start hook diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb index 70a2e44635..7eb9de042e 100644 --- a/lib/chef/policy_builder/policyfile.rb +++ b/lib/chef/policy_builder/policyfile.rb @@ -177,16 +177,17 @@ class Chef # # @return [Chef::RunContext] def setup_run_context(specific_recipes = nil, run_context = nil) + run_context ||= Chef::RunContext.new + run_context.node = node + run_context.events = events + Chef::Cookbook::FileVendor.fetch_from_remote(api_service) sync_cookbooks cookbook_collection = Chef::CookbookCollection.new(cookbooks_to_sync) cookbook_collection.validate! cookbook_collection.install_gems(events) - run_context ||= Chef::RunContext.new - run_context.node = node run_context.cookbook_collection = cookbook_collection - run_context.events = events setup_chef_class(run_context) diff --git a/lib/chef/provider/package/chocolatey.rb b/lib/chef/provider/package/chocolatey.rb index a09bbf55de..1bb379f471 100644 --- a/lib/chef/provider/package/chocolatey.rb +++ b/lib/chef/provider/package/chocolatey.rb @@ -1,5 +1,5 @@ # -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,13 +84,13 @@ class Chef # choco does not support installing multiple packages with version pins name_has_versions.each do |name, version| - choco_command("install -y --version", version, cmd_args, name) + choco_command("install", "-y", "--version", version, cmd_args, name) end # but we can do all the ones without version pins at once unless name_nil_versions.empty? cmd_names = name_nil_versions.keys - choco_command("install -y", cmd_args, *cmd_names) + choco_command("install", "-y", cmd_args, *cmd_names) end end @@ -106,13 +106,13 @@ class Chef # choco does not support installing multiple packages with version pins name_has_versions.each do |name, version| - choco_command("upgrade -y --version", version, cmd_args, name) + choco_command("upgrade", "-y", "--version", version, cmd_args, name) end # but we can do all the ones without version pins at once unless name_nil_versions.empty? cmd_names = name_nil_versions.keys - choco_command("upgrade -y", cmd_args, *cmd_names) + choco_command("upgrade", "-y", cmd_args, *cmd_names) end end @@ -121,7 +121,7 @@ class Chef # @param names [Array<String>] array of package names to install # @param versions [Array<String>] array of versions to install def remove_package(names, versions) - choco_command("uninstall -y", cmd_args(include_source: false), *names) + choco_command("uninstall", "-y", cmd_args(include_source: false), *names) end # Choco does not have dpkg's distinction between purge and remove @@ -172,7 +172,7 @@ class Chef # @param args [String] variable number of string arguments # @return [Mixlib::ShellOut] object returned from shell_out! def choco_command(*args) - shell_out!(args_to_string(choco_exe, *args), returns: new_resource.returns) + shell_out!(choco_exe, *args, returns: new_resource.returns) end # Use the available_packages Hash helper to create an array suitable for @@ -210,18 +210,8 @@ class Chef # @return [String] options from new_resource or empty string def cmd_args(include_source: true) cmd_args = [ new_resource.options ] - cmd_args.push( "-source #{new_resource.source}" ) if new_resource.source && include_source - args_to_string(*cmd_args) - end - - # Helper to nicely convert variable string args into a single command line. It - # will compact nulls or empty strings and join arguments with single spaces, without - # introducing any double-spaces for missing args. - # - # @param args [String] variable number of string arguments - # @return [String] nicely concatenated string or empty string - def args_to_string(*args) - args.reject { |i| i.nil? || i == "" }.join(" ") + cmd_args.push([ "-source", new_resource.source ]) if new_resource.source && include_source + cmd_args end # Available packages in chocolatey as a Hash of names mapped to versions @@ -236,8 +226,8 @@ class Chef package_name_array.each do |pkg| available_versions = begin - cmd = [ "list -r #{pkg}" ] - cmd.push( "-source #{new_resource.source}" ) if new_resource.source + cmd = [ "list", "-r", pkg ] + cmd.push( [ "-source", new_resource.source ] ) if new_resource.source cmd.push( new_resource.options ) if new_resource.options raw = parse_list_output(*cmd) @@ -255,7 +245,7 @@ class Chef # # @return [Hash] name-to-version mapping of installed packages def installed_packages - @installed_packages ||= Hash[*parse_list_output("list -l -r").flatten] + @installed_packages ||= Hash[*parse_list_output("list", "-l", "-r").flatten] @installed_packages end diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb index 76ef173ff5..6feae23686 100644 --- a/lib/chef/resource/chocolatey_package.rb +++ b/lib/chef/resource/chocolatey_package.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2017, 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"); @@ -30,7 +30,7 @@ class Chef allowed_actions :install, :upgrade, :remove, :purge, :reconfig # windows can't take Array options yet - property :options, String, + property :options, [String, Array], description: "One (or more) additional options that are passed to the command." property :package_name, [String, Array], diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 7a5924a3c7..d849679680 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -66,7 +66,7 @@ class Chef # # @return [Chef::CookbookCollection] # - attr_accessor :cookbook_collection + attr_reader :cookbook_collection # # Resource Definitions for this run. Populated when the files in @@ -188,11 +188,11 @@ class Chef # @param events [EventDispatch::Dispatcher] The event dispatcher for this # run. # - def initialize(node = nil, cookbook_collection = {}, events = nil, logger = nil) + def initialize(node = nil, cookbook_collection = nil, events = nil, logger = nil) @events = events @logger = logger || Chef::Log.with_child - @cookbook_collection = cookbook_collection self.node = node if node + self.cookbook_collection = cookbook_collection if cookbook_collection @definitions = {} @loaded_recipes_hash = {} @loaded_attributes_hash = {} @@ -205,6 +205,10 @@ class Chef def node=(node) @node = node node.run_context = self + end + + def cookbook_collection=(cookbook_collection) + @cookbook_collection = cookbook_collection node.set_cookbook_attribute end diff --git a/lib/chef/version.rb b/lib/chef/version.rb index d55b5fc8f7..3b2c2ef642 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -23,7 +23,7 @@ require_relative "version_string" class Chef CHEF_ROOT = File.expand_path("../..", __FILE__) - VERSION = Chef::VersionString.new("15.2.29") + VERSION = Chef::VersionString.new("15.3.7") end # diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock index a25b39a95e..09d7e4f6f6 100644 --- a/omnibus/Gemfile.lock +++ b/omnibus/Gemfile.lock @@ -1,9 +1,9 @@ GIT remote: https://github.com/chef/omnibus - revision: c4c0c518caf5c559ddf3d0ae773013d5dbc6bd3c + revision: c872e61c30d2b3f88ead03bd1254ff96d37059a3 branch: master specs: - omnibus (6.1.2) + omnibus (6.1.3) aws-sdk-s3 (~> 1) chef-sugar (>= 3.3) cleanroom (~> 1.0) @@ -18,7 +18,7 @@ GIT GIT remote: https://github.com/chef/omnibus-software - revision: 5fa35959f6efb0a5a745c46e4b0431a2826934da + revision: b851a32e09a384cad768a6d44df267ffe920cfc2 branch: master specs: omnibus-software (4.0.0) @@ -28,13 +28,13 @@ GIT GEM remote: https://rubygems.org/ specs: - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) artifactory (3.0.5) awesome_print (1.8.0) aws-eventstream (1.0.3) - aws-partitions (1.202.0) - aws-sdk-core (3.62.0) + aws-partitions (1.208.0) + aws-sdk-core (3.66.0) aws-eventstream (~> 1.0, >= 1.0.2) aws-partitions (~> 1.0) aws-sigv4 (~> 1.1) @@ -42,7 +42,7 @@ GEM aws-sdk-kms (1.24.0) aws-sdk-core (~> 3, >= 3.61.1) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.46.0) + aws-sdk-s3 (1.48.0) aws-sdk-core (~> 3, >= 3.61.1) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) @@ -207,7 +207,7 @@ GEM mixlib-cli (2.1.1) mixlib-config (3.0.1) tomlrb - mixlib-install (3.11.18) + mixlib-install (3.11.21) mixlib-shellout mixlib-versioning thor @@ -258,7 +258,7 @@ GEM plist (3.5.0) progressbar (1.10.1) proxifier (1.0.3) - public_suffix (3.1.1) + public_suffix (4.0.1) rack (2.0.7) retryable (3.0.4) ruby-progressbar (1.10.1) @@ -271,15 +271,15 @@ GEM solve (4.0.2) molinillo (~> 0.6) semverse (>= 1.1, < 4.0) - strings (0.1.5) + strings (0.1.6) strings-ansi (~> 0.1) unicode-display_width (~> 1.5) unicode_utils (~> 1.4) strings-ansi (0.1.0) - structured_warnings (0.3.0) + structured_warnings (0.4.0) syslog-logger (1.6.8) systemu (2.6.5) - test-kitchen (2.2.5) + test-kitchen (2.3.1) bcrypt_pbkdf (~> 1.0) ed25519 (~> 1.2) license-acceptance (~> 1.0, >= 1.0.11) @@ -303,9 +303,9 @@ GEM net-ssh (>= 2.9, < 6.0) winrm (~> 2.0) winrm-fs (~> 1.0) - tty-box (0.4.0) + tty-box (0.4.1) pastel (~> 0.7.2) - strings (~> 0.1.5) + strings (~> 0.1.6) tty-cursor (~> 0.7) tty-color (0.5.0) tty-cursor (0.7.0) diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb index 96342de8db..1f33f9be1f 100644 --- a/omnibus_overrides.rb +++ b/omnibus_overrides.rb @@ -6,7 +6,7 @@ # software here: bundle exec rake dependencies:update_omnibus_gemfile_lock override :rubygems, version: "3.0.3" # rubygems ships its own bundler which may differ from bundler defined below and then we get double bundler which results in performance issues / CLI warnings. Make sure these versions match before bumping either. override :bundler, version: "1.17.2" # currently pinned to what ships in Ruby to prevent double bundler -override "nokogiri", version: "1.10.2" +override "libarchive", version: "3.4.0" override "libffi", version: "3.2.1" override "libiconv", version: "1.15" override "liblzma", version: "5.2.4" @@ -16,13 +16,14 @@ override "libxslt", version: "1.1.30" override "libyaml", version: "0.1.7" override "makedepend", version: "1.0.5" override "ncurses", version: "5.9" +override "nokogiri", version: "1.10.2" +override "openssl", version: "1.0.2s" override "pkg-config-lite", version: "0.28-1" override "ruby", version: "2.6.3" override "ruby-windows-devkit-bash", version: "3.1.23-4-msys-1.0.18" override "util-macros", version: "1.19.0" override "xproto", version: "7.0.28" override "zlib", version: "1.2.11" -override "openssl", version: "1.0.2s" # we build both a chef and ohai omnibus-software defintion which create the # chef-client and ohai binstubs. Out of the box the ohai definition uses whatever diff --git a/scripts/bk_tests/bk_win_functional.ps1 b/scripts/bk_tests/bk_win_functional.ps1 new file mode 100644 index 0000000000..06695ccd97 --- /dev/null +++ b/scripts/bk_tests/bk_win_functional.ps1 @@ -0,0 +1,13 @@ +echo "--- system details" +$Properties = 'Caption', 'CSName', 'Version', 'BuildType', 'OSArchitecture' +Get-CimInstance Win32_OperatingSystem | Select-Object $Properties | Format-Table -AutoSize +ruby -v +bundle --version + +echo "--- bundle install" +bundle install --jobs=3 --retry=3 --without omnibus_package docgen chefstyle + +echo "+++ bundle exec rake" +bundle exec rake spec:functional + +exit $LASTEXITCODE
\ No newline at end of file diff --git a/scripts/bk_tests/bk_win_integration.ps1 b/scripts/bk_tests/bk_win_integration.ps1 new file mode 100644 index 0000000000..c6cdd5e2b1 --- /dev/null +++ b/scripts/bk_tests/bk_win_integration.ps1 @@ -0,0 +1,13 @@ +echo "--- system details" +$Properties = 'Caption', 'CSName', 'Version', 'BuildType', 'OSArchitecture' +Get-CimInstance Win32_OperatingSystem | Select-Object $Properties | Format-Table -AutoSize +ruby -v +bundle --version + +echo "--- bundle install" +bundle install --jobs=3 --retry=3 --without omnibus_package docgen chefstyle + +echo "+++ bundle exec rake" +bundle exec rake spec:integration + +exit $LASTEXITCODE
\ No newline at end of file diff --git a/scripts/bk_tests/bk_win_unit.ps1 b/scripts/bk_tests/bk_win_unit.ps1 new file mode 100644 index 0000000000..48ad3fe283 --- /dev/null +++ b/scripts/bk_tests/bk_win_unit.ps1 @@ -0,0 +1,14 @@ +echo "--- system details" +$Properties = 'Caption', 'CSName', 'Version', 'BuildType', 'OSArchitecture' +Get-CimInstance Win32_OperatingSystem | Select-Object $Properties | Format-Table -AutoSize +ruby -v +bundle --version + +echo "--- bundle install" +bundle install --jobs=3 --retry=3 --without omnibus_package docgen chefstyle + +echo "+++ bundle exec rake" +bundle exec rake spec:unit +bundle exec rake component_specs + +exit $LASTEXITCODE
\ No newline at end of file diff --git a/spec/functional/resource/chocolatey_package_spec.rb b/spec/functional/resource/chocolatey_package_spec.rb index c5590b2d88..a2728b3fa9 100644 --- a/spec/functional/resource/chocolatey_package_spec.rb +++ b/spec/functional/resource/chocolatey_package_spec.rb @@ -1,6 +1,6 @@ # # Author:: Matt Wrock (<matt@mattwrock.com>) -# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2016-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,6 +75,24 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do subject.package_name "blah" expect { subject.run_action(:install) }.to raise_error Chef::Exceptions::Package end + + it "installs with an option as a string" do + subject.options "--force --confirm" + subject.run_action(:install) + expect(package_list.call).to eq("#{package_name}|2.0") + end + + it "installs with multiple options as a string" do + subject.options "--force --confirm" + subject.run_action(:install) + expect(package_list.call).to eq("#{package_name}|2.0") + end + + it "installs with multiple options as an array" do + subject.options [ "--force", "--confirm" ] + subject.run_action(:install) + expect(package_list.call).to eq("#{package_name}|2.0") + end end context "upgrading a package" do diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb index 68cfd015ab..b1763da1f0 100644 --- a/spec/integration/client/client_spec.rb +++ b/spec/integration/client/client_spec.rb @@ -369,6 +369,28 @@ describe "chef-client" do end end + when_the_repository "has a cookbook that outputs some node attributes" do + before do + file "cookbooks/x/recipes/default.rb", <<~'EOM' + puts "COOKBOOKS: #{node[:cookbooks]}" + EOM + file "cookbooks/x/metadata.rb", <<~EOM + name 'x' + version '0.0.1' + EOM + file "config/client.rb", <<~EOM + local_mode true + cookbook_path "#{path_to("cookbooks")}" + EOM + end + + it "should have a cookbook attribute" do + result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork", cwd: chef_dir) + result.error! + expect(result.stdout).to include('COOKBOOKS: {"x"=>{"version"=>"0.0.1"}}') + end + end + when_the_repository "has a cookbook that should fail chef_version checks" do before do file "cookbooks/x/recipes/default.rb", "" diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb index 9fd7664ddd..99fb7b5787 100644 --- a/spec/integration/knife/raw_spec.rb +++ b/spec/integration/knife/raw_spec.rb @@ -19,11 +19,11 @@ require "support/shared/integration/integration_helper" require "support/shared/context/config" require "chef/knife/raw" require "chef/knife/show" +require "tiny_server" describe "knife raw", :workstation do include IntegrationSupport include KnifeSupport - include AppServerSupport include_context "default config options" @@ -185,19 +185,29 @@ describe "knife raw", :workstation do end context "When a server returns raw json" do - before :each do - Chef::Config.chef_server_url = "http://localhost:9018" - app = lambda do |env| - [200, { "Content-Type" => "application/json" }, ['{ "x": "y", "a": "b" }'] ] + def start_tiny_server(server_opts = {}) + @server = TinyServer::Manager.new(server_opts) + @server.start + @api = TinyServer::API.instance + @api.clear + + @api.get("/blah", 200, nil, { "Content-Type" => "application/json" }) do + '{ "x": "y", "a": "b" }' end - @raw_server_thread = start_app_server(app, 9018) + end + + def stop_tiny_server + @server.stop + @server = @api = nil + end + + before :each do + Chef::Config.chef_server_url = "http://localhost:9000" + start_tiny_server end after :each do - if @raw_server_thread - @raw_server_thread.kill - @raw_server_thread.join(30) - end + stop_tiny_server end it "knife raw /blah returns the prettified json" do @@ -217,19 +227,29 @@ describe "knife raw", :workstation do end context "When a server returns text" do - before :each do - Chef::Config.chef_server_url = "http://localhost:9018" - app = lambda do |env| - [200, { "Content-Type" => "text" }, ['{ "x": "y", "a": "b" }'] ] + def start_tiny_server(server_opts = {}) + @server = TinyServer::Manager.new(server_opts) + @server.start + @api = TinyServer::API.instance + @api.clear + + @api.get("/blah", 200, nil, { "Content-Type" => "text" }) do + '{ "x": "y", "a": "b" }' end - @raw_server_thread = start_app_server(app, 9018) + end + + def stop_tiny_server + @server.stop + @server = @api = nil + end + + before :each do + Chef::Config.chef_server_url = "http://localhost:9000" + start_tiny_server end after :each do - if @raw_server_thread - @raw_server_thread.kill - @raw_server_thread.join(30) - end + stop_tiny_server end it "knife raw /blah returns the raw text" do diff --git a/spec/integration/knife/redirection_spec.rb b/spec/integration/knife/redirection_spec.rb index 5e5ef27b9a..fe39315fe4 100644 --- a/spec/integration/knife/redirection_spec.rb +++ b/spec/integration/knife/redirection_spec.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser (<jkeiser@chef.io>) -# Copyright:: Copyright 2013-2018, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,6 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +require "tiny_server" require "support/shared/integration/integration_helper" require "support/shared/context/config" require "chef/knife/list" @@ -22,7 +23,21 @@ require "chef/knife/list" describe "redirection", :workstation do include IntegrationSupport include KnifeSupport - include AppServerSupport + + def start_tiny_server(real_chef_server_url, server_opts = {}) + @server = TinyServer::Manager.new(server_opts) + @server.start + @api = TinyServer::API.instance + @api.clear + + @api.get("/roles", 302, nil, { "Content-Type" => "text", "Location" => "#{real_chef_server_url}/roles" }) do + end + end + + def stop_tiny_server + @server.stop + @server = @api = nil + end include_context "default config options" @@ -30,20 +45,14 @@ describe "redirection", :workstation do before { role "x", {} } context "and another server redirects to it with 302" do - before :each do + before(:each) do real_chef_server_url = Chef::Config.chef_server_url - Chef::Config.chef_server_url = "http://localhost:9018" - app = lambda do |env| - [302, { "Content-Type" => "text", "Location" => "#{real_chef_server_url}#{env["PATH_INFO"]}" }, ["302 found"] ] - end - @redirector_server_thread = start_app_server(app, 9018) + Chef::Config.chef_server_url = "http://localhost:9000" + start_tiny_server(real_chef_server_url) end - after :each do - if @redirector_thread - @redirector_thread.kill - @redirector_thread.join(30) - end + after(:each) do + stop_tiny_server end it "knife list /roles returns the role" do diff --git a/spec/integration/knife/serve_spec.rb b/spec/integration/knife/serve_spec.rb index b0cdd8c070..ab293174d4 100644 --- a/spec/integration/knife/serve_spec.rb +++ b/spec/integration/knife/serve_spec.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser (<jkeiser@chef.io>) -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ require "chef/server_api" describe "knife serve", :workstation do include IntegrationSupport include KnifeSupport - include AppServerSupport def with_knife_serve exception = nil diff --git a/spec/support/shared/integration/app_server_support.rb b/spec/support/shared/integration/app_server_support.rb deleted file mode 100644 index 317a5a2679..0000000000 --- a/spec/support/shared/integration/app_server_support.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Author:: John Keiser (<jkeiser@chef.io>) -# Author:: Ho-Sheng Hsiao (<hosh@chef.io>) -# Copyright:: Copyright 2012-2018, Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "rack" -require "stringio" - -module AppServerSupport - def start_app_server(app, port) - server = nil - thread = Thread.new do - Rack::Handler::WEBrick.run(app, - Port: 9018, - AccessLog: [], - Logger: WEBrick::Log.new(StringIO.new, 7)) do |found_server| - server = found_server - end - end - Timeout.timeout(30) do - sleep(0.01) until server && server.status == :Running - end - thread - end -end diff --git a/spec/support/shared/integration/integration_helper.rb b/spec/support/shared/integration/integration_helper.rb index 6c0eca98be..f0dfd1dc43 100644 --- a/spec/support/shared/integration/integration_helper.rb +++ b/spec/support/shared/integration/integration_helper.rb @@ -1,7 +1,7 @@ # # Author:: John Keiser (<jkeiser@chef.io>) # Author:: Ho-Sheng Hsiao (<hosh@chef.io>) -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,6 @@ require "chef/config" require "chef/json_compat" require "chef/server_api" require "support/shared/integration/knife_support" -require "support/shared/integration/app_server_support" require "cheffish/rspec/chef_run_support" require "spec_helper" diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index 0773fc70fd..d4ed403197 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -1,6 +1,6 @@ # Author:: AJ Christensen (<aj@junglist.gen.nz>) -# 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"); @@ -85,7 +85,6 @@ describe Chef::Application::Client, "reconfigure" do allow(app).to receive(:trap) allow(app).to receive(:configure_logging).and_return(true) - Chef::Config[:interval] = 10 Chef::Config[:once] = false @@ -162,7 +161,7 @@ describe Chef::Application::Client, "reconfigure" do it_behaves_like "sets the configuration", "--no-fork", client_fork: false end - context "with an interval" do + context "with an interval", :unix_only do it_behaves_like "sets the configuration", "--interval 1800", client_fork: true end @@ -322,7 +321,7 @@ describe Chef::Application::Client, "reconfigure" do Chef::Config[:splay] = nil end - it "should terminal with message when interval is given" do + it "should terminate with message when interval is given" do Chef::Config[:interval] = 600 allow(ChefConfig).to receive(:windows?).and_return(false) expect(Chef::Application).to receive(:fatal!).with( @@ -340,8 +339,8 @@ Enable .* interval runs by setting `:client_fork = true` in your config file or allow(ChefConfig).to receive(:windows?).and_return(true) end - it "should not terminate" do - expect(Chef::Application).not_to receive(:fatal!) + it "should terminate" do + expect(Chef::Application).to receive(:fatal!) app.reconfigure end end diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb index 3f540d24e2..b70f959ab5 100644 --- a/spec/unit/application/solo_spec.rb +++ b/spec/unit/application/solo_spec.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen (<aj@junglist.gen.nz>) -# 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"); @@ -64,18 +64,13 @@ describe Chef::Application::Solo do end it "should terminate with message" do - expect(Chef::Application).to receive(:fatal!).with( - /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\./ - ) + expect(Chef::Application).to receive(:fatal!).with(/interval runs are (disabled|not supported)/) app.reconfigure end end end - describe "when in daemonized mode and no interval has been set" do + describe "when in daemonized mode and no interval has been set", :unix_only do before do Chef::Config[:daemonize] = true end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index e94f9b74ae..7a787d1f3f 100644 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen (<aj@junglist.gen.nz>) # 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"); diff --git a/spec/unit/knife/bootstrap/train_connector_spec.rb b/spec/unit/knife/bootstrap/train_connector_spec.rb index a2b7a571b0..dd000f7300 100644 --- a/spec/unit/knife/bootstrap/train_connector_spec.rb +++ b/spec/unit/knife/bootstrap/train_connector_spec.rb @@ -162,16 +162,29 @@ describe Chef::Knife::Bootstrap::TrainConnector do allow(SecureRandom).to receive(:alphanumeric).with(6).and_return(random) end - it "uses the *nix command to create the temp dir and sets ownership to logged-in user" do - expected_command = "mkdir -p #{dir} && sudo chown user1 '#{dir}'" - expect(subject).to receive(:run_command!).with(expected_command) - .and_return double("result", stdout: "\r\n") - expect(subject.temp_dir).to eq(dir) + context "uses the *nix command to create the temp dir and sets ownership to logged-in" do + it "with sudo privilege" do + subject.config[:sudo] = true + expected_command1 = "mkdir -p '#{dir}'" + expected_command2 = "chown user1 '#{dir}'" + expect(subject).to receive(:run_command!).with(expected_command1) + .and_return double("result", stdout: "\r\n") + expect(subject).to receive(:run_command!).with(expected_command2) + .and_return double("result", stdout: "\r\n") + expect(subject.temp_dir).to eq(dir) + end + + it "without sudo privilege" do + expected_command = "mkdir -p '#{dir}'" + expect(subject).to receive(:run_command!).with(expected_command) + .and_return double("result", stdout: "\r\n") + expect(subject.temp_dir).to eq(dir) + end end context "with noise in stderr" do - it "uses the *nix command to create the temp dir and sets ownership to logged-in user" do - expected_command = "mkdir -p #{dir} && sudo chown user1 '#{dir}'" + it "uses the *nix command to create the temp dir" do + expected_command = "mkdir -p '#{dir}'" expect(subject).to receive(:run_command!).with(expected_command) .and_return double("result", stdout: "sudo: unable to resolve host hostname.localhost\r\n" + "#{dir}\r\n") expect(subject.temp_dir).to eq(dir) diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index 5f4be8dfa2..752fcff1e3 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -1021,7 +1021,6 @@ describe Chef::Knife::Bootstrap do verify_host_key: nil, port: 9999, non_interactive: true, - pty: true, } end @@ -1076,7 +1075,6 @@ describe Chef::Knife::Bootstrap do verify_host_key: nil, # Config port: 12, # cli non_interactive: true, - pty: true, } end @@ -1128,7 +1126,6 @@ describe Chef::Knife::Bootstrap do sudo_password: "blah", verify_host_key: true, non_interactive: true, - pty: true, } end it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do @@ -1152,7 +1149,6 @@ describe Chef::Knife::Bootstrap do sudo: false, verify_host_key: "always", non_interactive: true, - pty: true, connection_timeout: 60, } end @@ -1504,7 +1500,6 @@ describe Chef::Knife::Bootstrap do let(:default_opts) do { non_interactive: true, - pty: true, forward_agent: false, connection_timeout: 60, } @@ -2003,6 +1998,19 @@ describe Chef::Knife::Bootstrap do expect(connection).to receive(:connect!) knife.do_connect({}) end + + context "when sshd confgiured with requiretty" do + let(:pty_err_msg) { "Sudo requires a TTY. Please see the README on how to configure sudo to allow for non-interactive usage." } + let(:expected_error) { Train::UserError.new(pty_err_msg, :sudo_no_tty) } + before do + allow(connection).to receive(:connect!).and_raise(expected_error) + end + it "retry with pty true request option" do + expect(Chef::Knife::Bootstrap::TrainConnector).to receive(:new).and_return(connection).exactly(2).times + expect(knife.ui).to receive(:warn).with("#{pty_err_msg} - trying with pty request") + expect { knife.do_connect({}) }.to raise_error(expected_error) + end + end end describe "validate_winrm_transport_opts!" do diff --git a/spec/unit/provider/package/chocolatey_spec.rb b/spec/unit/provider/package/chocolatey_spec.rb index 9b0cef4ef3..c263b3aa0a 100644 --- a/spec/unit/provider/package/chocolatey_spec.rb +++ b/spec/unit/provider/package/chocolatey_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, 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"); @@ -46,7 +46,7 @@ describe Chef::Provider::Package::Chocolatey do allow(provider).to receive(:choco_install_path).and_return(choco_install_path) allow(provider).to receive(:choco_exe).and_return(choco_exe) local_list_obj = double(stdout: local_list_stdout) - allow(provider).to receive(:shell_out_compacted!).with("#{choco_exe} list -l -r", { returns: [0], timeout: timeout }).and_return(local_list_obj) + allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-l", "-r", { returns: [0], timeout: timeout }).and_return(local_list_obj) end def allow_remote_list(package_names, args = nil) @@ -60,7 +60,11 @@ describe Chef::Provider::Package::Chocolatey do EOF remote_list_obj = double(stdout: remote_list_stdout) package_names.each do |pkg| - allow(provider).to receive(:shell_out_compacted!).with("#{choco_exe} list -r #{pkg}#{args}", { returns: [0], timeout: timeout }).and_return(remote_list_obj) + if args + allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-r", pkg, *args, { returns: [0], timeout: timeout }).and_return(remote_list_obj) + else + allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-r", pkg, { returns: [0], timeout: timeout }).and_return(remote_list_obj) + end end end @@ -182,7 +186,7 @@ describe Chef::Provider::Package::Chocolatey do it "should install a single package" do allow_remote_list(["git"]) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -193,7 +197,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["git"]) new_resource.timeout(timeout) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -222,7 +226,7 @@ describe Chef::Provider::Package::Chocolatey do new_resource.package_name("ConEmu") new_resource.version("15.10.25.1") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "--version", "15.10.25.1", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -235,7 +239,7 @@ describe Chef::Provider::Package::Chocolatey do new_resource.package_name(%w{chocolatey ConEmu}) new_resource.version([nil, "15.10.25.1"]) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "--version", "15.10.25.1", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -245,7 +249,7 @@ describe Chef::Provider::Package::Chocolatey do new_resource.package_name("conemu") new_resource.version("15.10.25.1") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "--version", "15.10.25.1", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -255,8 +259,8 @@ describe Chef::Provider::Package::Chocolatey do new_resource.package_name(%w{ConEmu git}) new_resource.version(["15.10.25.1", nil]) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { returns: [0], timeout: timeout }).and_return(double) - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "--version", "15.10.25.1", "conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -265,27 +269,27 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(%w{git munin-node}) new_resource.package_name(%w{git munin-node}) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y git munin-node", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", "munin-node", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end context "when passing a source argument" do it "should pass options into the install command" do - allow_remote_list(["git"], " -source localpackages") + allow_remote_list(["git"], ["-source", "localpackages"]) new_resource.source("localpackages") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y -source localpackages git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "-source", "localpackages", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end end it "should pass options into the install command" do - allow_remote_list(["git"], " -force") + allow_remote_list(["git"], "-force") new_resource.options("-force") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y -force git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "-force", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -306,7 +310,7 @@ describe Chef::Provider::Package::Chocolatey do context "alternate source" do it "installing a package that does not exist throws an error" do - allow_remote_list(["package-does-not-exist"], " -source alternate_source") + allow_remote_list(["package-does-not-exist"], ["-source", "alternate_source"]) new_resource.package_name("package-does-not-exist") new_resource.source("alternate_source") provider.load_current_resource @@ -316,7 +320,7 @@ describe Chef::Provider::Package::Chocolatey do context "private source" do it "installing a package without auth options throws an error" do - allow_remote_list(["package-without-auth"], " -source auth_source") + allow_remote_list(["package-without-auth"], ["-source", "auth_source"]) new_resource.package_name("package-without-auth") new_resource.source("auth_source") provider.load_current_resource @@ -324,7 +328,7 @@ describe Chef::Provider::Package::Chocolatey do end it "installing a package with invalid credentials throws an error" do - allow_remote_list(["package-invalid-auth"], " -source auth_source -u user -p password") + allow_remote_list(["package-invalid-auth"], [ "-source", "auth_source", "-u user -p password"]) new_resource.package_name("package-invalid-auth") new_resource.source("auth_source") new_resource.options("-u user -p password") @@ -333,11 +337,11 @@ describe Chef::Provider::Package::Chocolatey do end it "installing a package with valid credentials" do - allow_remote_list(["git"], " -source auth_source -u user -p password") + allow_remote_list(["git"], [ "-source", "auth_source", "-u user -p password" ]) new_resource.source("auth_source") new_resource.options("-u user -p password") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} install -y -u user -p password -source auth_source git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "-u user -p password", "-source", "auth_source", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -348,7 +352,7 @@ describe Chef::Provider::Package::Chocolatey do it "should install a package that is not installed" do allow_remote_list(["git"]) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:upgrade) expect(new_resource).to be_updated_by_last_action end @@ -357,7 +361,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["ConEmu"]) new_resource.package_name("ConEmu") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:upgrade) expect(new_resource).to be_updated_by_last_action end @@ -366,7 +370,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["conemu"]) new_resource.package_name("conemu") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:upgrade) expect(new_resource).to be_updated_by_last_action end @@ -375,7 +379,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["chocolatey"]) new_resource.package_name("chocolatey") provider.load_current_resource - expect(provider).not_to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y chocolatey", { returns: [0], timeout: timeout }) + expect(provider).not_to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "chocolatey", { returns: [0], timeout: timeout }) provider.run_action(:upgrade) expect(new_resource).not_to be_updated_by_last_action end @@ -384,7 +388,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["git"]) new_resource.version("2.6.2") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y --version 2.6.2 git", { returns: [0], timeout: timeout }) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "--version", "2.6.2", "git", { returns: [0], timeout: timeout }) provider.run_action(:upgrade) expect(new_resource).to be_updated_by_last_action end @@ -392,7 +396,7 @@ describe Chef::Provider::Package::Chocolatey do it "upgrading multiple packages uses a single command" do allow_remote_list(%w{conemu git}) new_resource.package_name(%w{conemu git}) - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} upgrade -y conemu git", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "conemu", "git", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:upgrade) expect(new_resource).to be_updated_by_last_action end @@ -413,7 +417,7 @@ describe Chef::Provider::Package::Chocolatey do context "alternate source" do it "installing a package that does not exist throws an error" do - allow_remote_list(["package-does-not-exist"], " -source alternate_source") + allow_remote_list(["package-does-not-exist"], ["-source", "alternate_source"]) new_resource.package_name("package-does-not-exist") new_resource.source("alternate_source") provider.load_current_resource @@ -444,7 +448,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["ConEmu"]) new_resource.package_name("ConEmu") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} uninstall -y ConEmu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "uninstall", "-y", "ConEmu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:remove) expect(new_resource).to be_updated_by_last_action end @@ -453,7 +457,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(["conemu"]) new_resource.package_name("conemu") provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} uninstall -y conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "uninstall", "-y", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:remove) expect(new_resource).to be_updated_by_last_action end @@ -463,7 +467,7 @@ describe Chef::Provider::Package::Chocolatey do allow_remote_list(%w{git conemu}) new_resource.package_name(%w{git conemu}) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted!).with("#{choco_exe} uninstall -y conemu", { returns: [0], timeout: timeout }).and_return(double) + expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "uninstall", "-y", "conemu", { returns: [0], timeout: timeout }).and_return(double) provider.run_action(:remove) expect(new_resource).to be_updated_by_last_action end |