diff options
author | Noah Kantrowitz <noah@coderanger.net> | 2017-03-21 22:42:02 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-21 22:42:02 -0700 |
commit | 15ada49514c9d256872f9fe53edf6461f81098e0 (patch) | |
tree | 8a65efe8c8ae62765dc688b00067e3980d116789 | |
parent | 7ebe6c50e5d24dc2ceb6d58b83d986fe538485f1 (diff) | |
parent | 295b2a6c42f7f465b38edb4f338fe0b19452e80d (diff) | |
download | chef-15ada49514c9d256872f9fe53edf6461f81098e0.tar.gz |
Merge branch 'master' into easy-install-notes
Signed-off-by: Noah Kantrowitz <noah@coderanger.net>
90 files changed, 644 insertions, 2730 deletions
diff --git a/.gitignore b/.gitignore index 03d53ceb10..aaf9fa045e 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ kitchen-tests/nodes/* # Temporary files present during spec runs spec/data/test-dir +spec/data/nodes /config/ # acceptance binstubs diff --git a/.travis.yml b/.travis.yml index 336e1a20a5..3afe4670c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -253,43 +253,6 @@ matrix: # env: # - FEDORA=latest # - KITCHEN_YAML=.kitchen.travis.yml -# can re-enable amazonlinux when we get a build in current that contains the crypto libs added in #5687 -# - rvm: 2.3.3 -# services: docker -# sudo: required -# gemfile: kitchen-tests/Gemfile -# before_install: -# - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2) -# - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2) -# bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen -# before_script: -# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) -# - cd kitchen-tests -# script: -# - travis_wait bundle exec kitchen test webapp-amazonlinux -# after_failure: -# - cat .kitchen/logs/kitchen.log -# env: -# - AMAZONLINUX=LATEST -# - KITCHEN_YAML=.kitchen.travis.yml - - rvm: 2.3.3 - services: docker - sudo: required - gemfile: kitchen-tests/Gemfile - before_install: - - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2) - - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2) - bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen - before_script: - - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) - - cd kitchen-tests - script: - - bundle exec kitchen test awesome-customers-ubuntu-ubuntu-1404 - after_failure: - - cat .kitchen/logs/kitchen.log - env: - - AWESOME_CUSTOMERS_UBUNTU=1 - - KITCHEN_YAML=.kitchen.travis.yml - rvm: 2.3.3 services: docker sudo: required @@ -302,13 +265,49 @@ matrix: - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) - cd kitchen-tests script: - - bundle exec kitchen test awesome-customers-rhel-centos-7 + - travis_wait bundle exec kitchen test webapp-amazonlinux after_failure: - cat .kitchen/logs/kitchen.log env: - - AWESOME_CUSTOMERS_RHEL=1 + - AMAZONLINUX=LATEST - KITCHEN_YAML=.kitchen.travis.yml - ### END TEST KITCHEN ONLY ### +# - rvm: 2.3.3 +# services: docker +# sudo: required +# gemfile: kitchen-tests/Gemfile +# before_install: +# - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2) +# - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2) +# bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen +# before_script: +# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) +# - cd kitchen-tests +# script: +# - bundle exec kitchen test awesome-customers-ubuntu-ubuntu-1404 +# after_failure: +# - cat .kitchen/logs/kitchen.log +# env: +# - AWESOME_CUSTOMERS_UBUNTU=1 +# - KITCHEN_YAML=.kitchen.travis.yml +# - rvm: 2.3.3 +# services: docker +# sudo: required +# gemfile: kitchen-tests/Gemfile +# before_install: +# - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2) +# - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2) +# bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen +# before_script: +# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) +# - cd kitchen-tests +# script: +# - bundle exec kitchen test awesome-customers-rhel-centos-7 +# after_failure: +# - cat .kitchen/logs/kitchen.log +# env: +# - AWESOME_CUSTOMERS_RHEL=1 +# - KITCHEN_YAML=.kitchen.travis.yml +# ### END TEST KITCHEN ONLY ### - rvm: 2.3.3 sudo: required dist: trusty diff --git a/CHANGELOG.md b/CHANGELOG.md index a325b05065..71aae4e89c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,53 @@ This changelog reflects the current state of chef's master branch on github and may not reflect the current released version of chef, which is [![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef). -## [v13.0.42](https://github.com/chef/chef/tree/v13.0.42) (2017-03-15) -[Full Changelog](https://github.com/chef/chef/compare/v12.19.36...v13.0.42) +## [v13.0.62](https://github.com/chef/chef/tree/v13.0.62) (2017-03-21) +[Full Changelog](https://github.com/chef/chef/compare/v13.0.62...v13.0.62) + +**Merged pull requests:** + +- Chef-13: Simplify DSL creation [\#5934](https://github.com/chef/chef/pull/5934) ([lamont-granquist](https://github.com/lamont-granquist)) + +## [v13.0.62](https://github.com/chef/chef/tree/v13.0.62) (2017-03-21) +[Full Changelog](https://github.com/chef/chef/compare/v12.19.36...v13.0.62) **Closed issues:** +- `group` resource not idempotent on Windows \(12.19.36\) [\#5857](https://github.com/chef/chef/issues/5857) +- Chef doesn't have access to a file created by itself, under the ownership of SYSTEM? [\#5844](https://github.com/chef/chef/issues/5844) - apt\_repository can't identify key fingerprints when gnupg 2.1.x is used [\#5831](https://github.com/chef/chef/issues/5831) +- FATAL: NoMethodError: undefined method `password' for Chef::Resource::Execute [\#5824](https://github.com/chef/chef/issues/5824) - We should update the default data bag encryption version for Chef 13 [\#5819](https://github.com/chef/chef/issues/5819) **Merged pull requests:** +- Chef-13: Remove deprecated Chef::Client attrs [\#5932](https://github.com/chef/chef/pull/5932) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove method\_missing from the DSL [\#5930](https://github.com/chef/chef/pull/5930) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove node\_map back-compat [\#5926](https://github.com/chef/chef/pull/5926) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove deprecated run\_context methods [\#5925](https://github.com/chef/chef/pull/5925) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove Chef::ShellOut [\#5923](https://github.com/chef/chef/pull/5923) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove old platform mapping code [\#5914](https://github.com/chef/chef/pull/5914) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove the old rake tasks [\#5913](https://github.com/chef/chef/pull/5913) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: raise on properties redefining inherited methods [\#5912](https://github.com/chef/chef/pull/5912) ([lamont-granquist](https://github.com/lamont-granquist)) +- fix node\#debug\_value access through arrays [\#5911](https://github.com/chef/chef/pull/5911) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: Nillable properties [\#5907](https://github.com/chef/chef/pull/5907) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: freeze merged node attribute [\#5905](https://github.com/chef/chef/pull/5905) ([lamont-granquist](https://github.com/lamont-granquist)) +- bump ruby to 2.3.3 [\#5902](https://github.com/chef/chef/pull/5902) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: Remove declare\_resource create\_if\_missing API [\#5900](https://github.com/chef/chef/pull/5900) ([lamont-granquist](https://github.com/lamont-granquist)) +- Properly use chef-shell in SoloSession by deprecating old behavior into SoloLegacySession [\#5898](https://github.com/chef/chef/pull/5898) ([afiune](https://github.com/afiune)) +- Chef-13: properly deep dup Node\#to\_hash [\#5896](https://github.com/chef/chef/pull/5896) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: remove method\_missing access to node object. [\#5895](https://github.com/chef/chef/pull/5895) ([lamont-granquist](https://github.com/lamont-granquist)) +- Jeremymv2/cheffs optimizations [\#5890](https://github.com/chef/chef/pull/5890) ([jeremymv2](https://github.com/jeremymv2)) - Changed EOP to 'EOP' to avoid content expansion [\#5888](https://github.com/chef/chef/pull/5888) ([afiune](https://github.com/afiune)) - Compress debs and rpms with xz [\#5884](https://github.com/chef/chef/pull/5884) ([thommay](https://github.com/thommay)) +- Chef-13: Chef::Resource cleanup [\#5882](https://github.com/chef/chef/pull/5882) ([lamont-granquist](https://github.com/lamont-granquist)) - Fix apt\_repository for latest os version 16.10 [\#5874](https://github.com/chef/chef/pull/5874) ([afiune](https://github.com/afiune)) -- convert additional resource methods to properties [\#5871](https://github.com/chef/chef/pull/5871) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: convert additional resource methods to properties [\#5871](https://github.com/chef/chef/pull/5871) ([lamont-granquist](https://github.com/lamont-granquist)) - Add the ability to blacklist attributes from being saved to the chef server [\#5868](https://github.com/chef/chef/pull/5868) ([robmul](https://github.com/robmul)) +- Chef-13: remove supports API from Chef::Resource [\#5863](https://github.com/chef/chef/pull/5863) ([lamont-granquist](https://github.com/lamont-granquist)) +- HTTP: add debug long for non-JSON response [\#5858](https://github.com/chef/chef/pull/5858) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13 remove resource cloning and 3694 warnings [\#5856](https://github.com/chef/chef/pull/5856) ([lamont-granquist](https://github.com/lamont-granquist)) +- Chef-13: support why-run by default [\#5853](https://github.com/chef/chef/pull/5853) ([lamont-granquist](https://github.com/lamont-granquist)) +- bump major to chef-13 [\#5833](https://github.com/chef/chef/pull/5833) ([lamont-granquist](https://github.com/lamont-granquist)) ## [v12.19.33](https://github.com/chef/chef/tree/v12.19.33) (2017-02-16) [Full Changelog](https://github.com/chef/chef/compare/v12.18.31...v12.19.33) diff --git a/Gemfile.lock b/Gemfile.lock index 04388a32a7..77611b32cb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,10 +113,10 @@ GIT PATH remote: . specs: - chef (13.0.43) + chef (13.0.63) addressable bundler (>= 1.10) - chef-config (= 13.0.43) + chef-config (= 13.0.63) chef-zero (>= 4.8) diff-lcs (~> 1.2, >= 1.2.4) erubis (~> 2.7) @@ -142,10 +142,10 @@ PATH specinfra (~> 2.10) syslog-logger (~> 1.6) uuidtools (~> 2.1.5) - chef (13.0.43-universal-mingw32) + chef (13.0.63-universal-mingw32) addressable bundler (>= 1.10) - chef-config (= 13.0.43) + chef-config (= 13.0.63) chef-zero (>= 4.8) diff-lcs (~> 1.2, >= 1.2.4) erubis (~> 2.7) @@ -186,7 +186,7 @@ PATH PATH remote: chef-config specs: - chef-config (13.0.43) + chef-config (13.0.63) addressable fuzzyurl mixlib-config (~> 2.0) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2f78353d37..aa8d612d81 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -82,6 +82,51 @@ n["foo"] << "buzz" before this would have mutated the original string in-place so that `node["foo"]` and `node.default["foo"]` would have changed to "fizzbuzz" while now they remain "fizz" and only the mutable `n["foo"]` copy is changed to "fizzbuzz". +### Freezing immutable merged attributes + +Since Chef 11 merged node attributes have been intended to be immutable but the merged strings have not been frozen. In Chef 13, in the +process of merging the node attributes strings and other simple objects are dup'd and frozen. In order to get a mutable copy, you can +now correctly use the `node.dup` or `node.to_hash` methods, or you should mutate the object correctly through its precedence level like +`node.default["some_string"] << "appending_this"`. + +### The Chef::REST API has been removed + +It has been fully replaced with `Chef::ServerAPI` in chef-client code. + +### Properties overriding methods now raise an error + +Defining a property that overrides methods defined on the base ruby `Object` or on `Chef::Resource` itself can cause large amounts of +confusion. A simple example is `property :hash` which overrides the Object#hash method which will confuse ruby when the Custom Resource +is placed into the Chef::ResourceCollection which uses a Hash internally which expects to call Object#hash to get a unique id for the +object. Attempting to create `property :action` would also override the Chef::Resource#action method which is unlikely to end well for +the user. Overriding inherited properties is still supported. + +### `chef-shell` now supports solo and legacy solo modes + +Running `chef-shell -s` or `chef-shell --solo` will give you an experience consistent with `chef-solo`. `chef-shell --solo-legacy-mode` +will give you an experience consistent with `chef-solo --legacy-mode`. + +### Chef::Platform.set and related methods have been removed + +The deprecated code has been removed. All providers and resources should now be using Chef >= 12.0 `provides` syntax. + +### Remove `sort` option for the Search API + +This option has been unimplemented on the server side for years, so any use of it has been pointless. + +### Remove Chef::ShellOut + +This was deprecated and replaced a long time ago with mixlib-shellout and the shell_out mixin. + +### Remove `method_missing` from the Recipe DSL + +The core of chef hasn't used this to implement the Recipe DSL since 12.5.1 and its unlikely that any external code depended upon it. + +### Simplify Recipe DSL wiring + +Support for actions with spaces and hyphens in the action name has been dropped. Resources and property names with spaces and hyphens +most likely never worked in Chef-12. UTF-8 characters have always been supported and still are. + ### `easy_install` resource has been removed The Python `easy_install` package installer has been deprecated for many years, @@ -1 +1 @@ -13.0.43
\ No newline at end of file +13.0.63
\ No newline at end of file diff --git a/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb b/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb index d5d2e1380b..cf0b4eda5d 100644 --- a/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb +++ b/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb @@ -32,7 +32,7 @@ module KitchenAcceptance property :artifactory_username, String, default: lazy { ENV["ARTIFACTORY_USERNAME"] ? ENV["ARTIFACTORY_USERNAME"] : "" } property :artifactory_password, String, default: lazy { ENV["ARTIFACTORY_PASSWORD"] ? ENV["ARTIFACTORY_PASSWORD"] : "" } property :env, Hash, default: {} - property :kitchen_options, String, default: lazy { ENV["PROJECT_NAME"] ? "-c -l debug" : "-c" } + property :kitchen_options, String, default: "-c" action :run do diff --git a/acceptance/basics/test/integration/chef-current-install/serverspec/chef_client_spec.rb b/acceptance/basics/test/integration/chef-current-install/serverspec/chef_client_spec.rb index dd0e0e4e34..7bdb4e4ed3 100644 --- a/acceptance/basics/test/integration/chef-current-install/serverspec/chef_client_spec.rb +++ b/acceptance/basics/test/integration/chef-current-install/serverspec/chef_client_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" gem_path = "/opt/chef/embedded/bin/gem" -white_list = %w{chef-config json rake} +white_list = %w{addressable chef-config json rake} describe "gem list" do it "should not have non-whitelisted duplicate gems" do diff --git a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb index 73f5151bca..5716b97737 100644 --- a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb +++ b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb @@ -12,15 +12,16 @@ class TopCookbooks < Chef::Resource cookbook_kitchen "#{command} git" do end - cookbook_kitchen "#{command} learn-the-basics-ubuntu" do - repository "learn-chef/learn-chef-acceptance" - cookbook_relative_dir "cookbooks/learn-the-basics-ubuntu" - end + # FIXME: waiting for https://github.com/learn-chef/learn-chef-acceptance/pull/23 + # cookbook_kitchen "#{command} learn-the-basics-ubuntu" do + # repository "learn-chef/learn-chef-acceptance" + # cookbook_relative_dir "cookbooks/learn-the-basics-ubuntu" + # end - cookbook_kitchen "#{command} learn-the-basics-windows" do - repository "learn-chef/learn-chef-acceptance" - cookbook_relative_dir "cookbooks/learn-the-basics-windows" - end + # cookbook_kitchen "#{command} learn-the-basics-windows" do + # repository "learn-chef/learn-chef-acceptance" + # cookbook_relative_dir "cookbooks/learn-the-basics-windows" + # end cookbook_kitchen "#{command} powershell" do end diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index 3153ee8126..58b39d9fb1 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 = "13.0.43" + VERSION = "13.0.63" end # diff --git a/kitchen-tests/Berksfile b/kitchen-tests/Berksfile index 5319e45a19..09e4cea33a 100644 --- a/kitchen-tests/Berksfile +++ b/kitchen-tests/Berksfile @@ -8,6 +8,6 @@ cookbook "php", "~> 1.5.0" cookbook "resolver", github: "chef-cookbooks/resolver" cookbook "awesome_customers_ubuntu_wrapper", path: "cookbooks/awesome_customers_ubuntu_wrapper" -cookbook "awesome_customers_ubuntu", github: "learn-chef/awesome_customers_ubuntu" +cookbook "awesome_customers_ubuntu", github: "lamont-granquist/awesome_customers_ubuntu", branch: "lcg/bump-mysql-version" cookbook "awesome_customers_rhel_wrapper", path: "cookbooks/awesome_customers_rhel_wrapper" -cookbook "awesome_customers_rhel", github: "learn-chef/awesome_customers_rhel" +cookbook "awesome_customers_rhel", github: "lamont-granquist/awesome_customers_rhel", branch: "lcg/bump-mysql-version" diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock index bf0adfee6c..51217e0602 100644 --- a/kitchen-tests/Berksfile.lock +++ b/kitchen-tests/Berksfile.lock @@ -1,12 +1,14 @@ DEPENDENCIES awesome_customers_rhel - git: https://github.com/learn-chef/awesome_customers_rhel.git - revision: b576fcf2988e2cdf156e7ba6ff59a94d556e16f1 + git: https://github.com/lamont-granquist/awesome_customers_rhel.git + revision: ed730957b1b75c8701c708e2deb0740ca8325322 + branch: lcg/bump-mysql-version awesome_customers_rhel_wrapper path: cookbooks/awesome_customers_rhel_wrapper awesome_customers_ubuntu - git: https://github.com/learn-chef/awesome_customers_ubuntu.git - revision: fea174c5855266f28218f76f00f6eff69e850244 + git: https://github.com/lamont-granquist/awesome_customers_ubuntu.git + revision: 9d40958413d0ed1ef1e68c74d41895158c724964 + branch: lcg/bump-mysql-version awesome_customers_ubuntu_wrapper path: cookbooks/awesome_customers_ubuntu_wrapper base @@ -23,7 +25,7 @@ GRAPH database (~> 6.0) firewall (~> 2.5) httpd (~> 0.4) - mysql (~> 7.0) + mysql (~> 8.0) mysql2_chef_gem (~> 1.1) selinux (~> 0.9) awesome_customers_rhel_wrapper (0.1.0) @@ -33,7 +35,7 @@ GRAPH database (~> 6.0) firewall (~> 2.5) httpd (~> 0.4) - mysql (~> 7.0) + mysql (~> 8.0) mysql2_chef_gem (~> 1.1) awesome_customers_ubuntu_wrapper (0.1.0) awesome_customers_ubuntu (>= 0.0.0) @@ -62,29 +64,31 @@ GRAPH chef-sugar (3.4.0) chef_hostname (0.5.0) compat_resource (12.16.3) - cron (4.0.0) + cron (4.1.0) + compat_resource (>= 0.0.0) database (6.1.1) postgresql (>= 1.0.0) firewall (2.5.4) chef-sugar (>= 0.0.0) httpd (0.4.5) compat_resource (>= 12.16.3) - iis (5.0.7) + iis (5.0.8) windows (>= 1.34.6) + inifile_chef_gem (0.1.0) + build-essential (>= 0.0.0) iptables (4.0.0) logrotate (2.1.0) compat_resource (>= 0.0.0) - mariadb (1.0.1) + mariadb (1.2.0) apt (>= 0.0.0) yum (>= 0.0.0) yum-epel (>= 0.0.0) + yum-scl (>= 0.0.0) mingw (2.0.0) seven_zip (>= 0.0.0) multipackage (4.0.0) compat_resource (>= 0.0.0) - mysql (7.2.0) - smf (>= 0.0.0) - yum-mysql-community (>= 0.0.0) + mysql (8.2.0) mysql2_chef_gem (1.1.0) build-essential (>= 0.0.0) mariadb (>= 0.0.0) @@ -106,23 +110,21 @@ GRAPH build-essential (>= 2.0.0) compat_resource (>= 12.16.3) openssl (>= 4.0) - rbac (1.0.3) resolver (2.0.1) selinux (0.9.0) seven_zip (2.0.2) windows (>= 1.2.2) - smf (2.2.8) - rbac (>= 1.0.1) sudo (3.3.1) ubuntu (2.0.1) apt (>= 0.0.0) users (4.0.3) - windows (2.1.1) + windows (3.0.0) ohai (>= 4.0.0) xml (3.1.1) build-essential (>= 0.0.0) yum (5.0.0) yum-epel (2.1.1) compat_resource (>= 12.16.3) - yum-mysql-community (2.0.3) - compat_resource (>= 12.16.3) + yum-scl (0.2.0) + inifile_chef_gem (>= 0.0.0) + yum (>= 0.0.0) diff --git a/lib/chef.rb b/lib/chef.rb index 3e161dc365..3d6b783253 100644 --- a/lib/chef.rb +++ b/lib/chef.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ require "chef/log" require "chef/config" require "chef/providers" require "chef/resources" -require "chef/shell_out" require "chef/daemon" diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index 1481338a9c..2705a930ae 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -23,7 +23,6 @@ require "chef/client" require "chef/config" require "chef/daemon" require "chef/log" -require "chef/rest" require "chef/config_fetcher" require "fileutils" require "chef/mixin/shell_out" diff --git a/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb b/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb index 8f9e554526..c16c5ad4d7 100644 --- a/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb +++ b/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb @@ -30,6 +30,7 @@ class Chef def initialize(name, parent, exists = nil) super(name, parent) @exists = exists + @this_object_cache = nil end def data_handler @@ -69,7 +70,7 @@ class Chef def exists? if @exists.nil? begin - rest.get(api_path) + @this_object_cache = rest.get(api_path) @exists = true rescue Net::HTTPServerException => e if e.response.code == "404" @@ -85,6 +86,8 @@ class Chef end def delete(recurse) + # free up cache - it will be hydrated on next check for exists? + @this_object_cache = nil rest.delete(api_path) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e, "Timeout deleting: #{e}") @@ -97,12 +100,12 @@ class Chef end def read + # Minimize the value (get rid of defaults) so the results don't look terrible Chef::JSONCompat.to_json_pretty(minimize_value(_read_json)) end def _read_json - # Minimize the value (get rid of defaults) so the results don't look terrible - root.get_json(api_path) + @this_object_cache ? JSON.parse(@this_object_cache) : root.get_json(api_path) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading: #{e}") rescue Net::HTTPServerException => e @@ -151,6 +154,9 @@ class Chef other_value = minimize_value(other_value) other_value_json = Chef::JSONCompat.to_json_pretty(other_value) + # free up cache - it will be hydrated on next check for exists? + @this_object_cache = nil + [ value == other_value, value_json, other_value_json ] end @@ -159,6 +165,9 @@ class Chef end def write(file_contents) + # free up cache - it will be hydrated on next check for exists? + @this_object_cache = nil + begin object = Chef::JSONCompat.parse(file_contents) rescue Chef::Exceptions::JSON::ParseError => e diff --git a/lib/chef/client.rb b/lib/chef/client.rb index c064d33209..b219fdfdd6 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -3,7 +3,7 @@ # Author:: Christopher Walters (<cw@chef.io>) # Author:: Christopher Brown (<cb@chef.io>) # Author:: Tim Hinderliter (<tim@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -894,15 +894,6 @@ class Chef # STDERR_FD = STDERR - # - # Deprecated writers - # - - include Chef::Mixin::Deprecation - deprecated_attr_writer :ohai, "There is no alternative. Leave ohai alone!" - deprecated_attr_writer :rest, "There is no alternative. Leave rest alone!" - deprecated_attr :runner, "There is no alternative. Leave runner alone!" - private attr_reader :override_runlist diff --git a/lib/chef/constants.rb b/lib/chef/constants.rb index f32c3e6654..d75b632173 100644 --- a/lib/chef/constants.rb +++ b/lib/chef/constants.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser <jkeiser@chef.io> -# Copyright:: Copyright 2015-2016, Chef Software Inc. +# Copyright:: Copyright 2015-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/dsl/method_missing.rb b/lib/chef/dsl/method_missing.rb deleted file mode 100644 index 2917a54ee8..0000000000 --- a/lib/chef/dsl/method_missing.rb +++ /dev/null @@ -1,75 +0,0 @@ -#-- -# Copyright:: Copyright 2008-2016 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. -# - -class Chef - module DSL - # @deprecated scheduled to die in a Chef 13 fire - module MethodMissing - def describe_self_for_error - if respond_to?(:name) - %Q{`#{self.class} "#{name}"'} - elsif respond_to?(:recipe_name) - %Q{`#{self.class} "#{recipe_name}"'} - else - to_s - end - end - - # DEPRECATED: - # method_missing must live for backcompat purposes until Chef 13. - def method_missing(method_symbol, *args, &block) - # - # If there is already DSL for this, someone must have called - # method_missing manually. Not a fan. Not. A. Fan. - # - if respond_to?(method_symbol) - Chef.deprecated(:internal_api, "Calling method_missing(#{method_symbol.inspect}) directly is deprecated in Chef 12 and will be removed in Chef 13. Use public_send() or send() instead.") - return send(method_symbol, *args, &block) - end - - # - # If a definition exists, then Chef::DSL::Definitions.add_definition was - # never called. DEPRECATED. - # - if run_context.definitions.has_key?(method_symbol.to_sym) - Chef.deprecated(:internal_api, "Definition #{method_symbol} (#{run_context.definitions[method_symbol.to_sym]}) was added to the run_context without calling Chef::DSL::Definitions.add_definition(#{method_symbol.to_sym.inspect}). This will become required in Chef 13.") - Chef::DSL::Definitions.add_definition(method_symbol) - return send(method_symbol, *args, &block) - end - - # - # See if the resource exists anyway. If the user had set - # Chef::Resource::Blah = <resource>, a deprecation warning will be - # emitted and the DSL method 'blah' will be added to the DSL. - # - resource_class = Chef::ResourceResolver.resolve(method_symbol, node: run_context ? run_context.node : nil) - if resource_class - Chef::DSL::Resources.add_resource_dsl(method_symbol) - return send(method_symbol, *args, &block) - end - - begin - super - rescue NoMethodError - raise NoMethodError, "No resource or method named `#{method_symbol}' for #{describe_self_for_error}" - rescue NameError - raise NameError, "No resource, method, or local variable named `#{method_symbol}' for #{describe_self_for_error}" - end - end - end - end -end diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb index e2bd070179..dedf291857 100644 --- a/lib/chef/dsl/recipe.rb +++ b/lib/chef/dsl/recipe.rb @@ -1,7 +1,7 @@ #-- # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,6 @@ require "chef/dsl/reboot_pending" require "chef/dsl/audit" require "chef/dsl/powershell" require "chef/dsl/core" -require "chef/dsl/method_missing" require "chef/mixin/lazy_module_include" class Chef @@ -60,8 +59,6 @@ class Chef include Chef::DSL::Powershell include Chef::DSL::Resources include Chef::DSL::Definitions - # method_missing will disappear in Chef 13 - include Chef::DSL::MethodMissing extend Chef::Mixin::LazyModuleInclude def resource_class_for(snake_case_name) diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb index 8a4e7968f2..36ec018500 100644 --- a/lib/chef/dsl/resources.rb +++ b/lib/chef/dsl/resources.rb @@ -39,12 +39,6 @@ class Chef declare_resource(#{dsl_name.inspect}, args[0], created_at: caller[0], &block) end EOM - rescue SyntaxError - # Handle the case where dsl_name has spaces, etc. - define_method(dsl_name.to_sym) do |*args, &block| - Chef.deprecated(:internal_api, "Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: #{args}") if args.size > 1 - declare_resource(dsl_name, args[0], created_at: caller[0], &block) - end end def self.remove_resource_dsl(dsl_name) diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb index 046d1c7c52..7fc76b28c0 100644 --- a/lib/chef/knife/search.rb +++ b/lib/chef/knife/search.rb @@ -37,12 +37,6 @@ class Chef banner "knife search INDEX QUERY (options)" - option :sort, - :short => "-o SORT", - :long => "--sort SORT", - :description => "The order to sort the results in", - :default => nil - option :start, :short => "-b ROW", :long => "--start ROW", @@ -92,7 +86,6 @@ class Chef result_count = 0 search_args = Hash.new - search_args[:sort] = config[:sort] if config[:sort] search_args[:start] = config[:start] if config[:start] search_args[:rows] = config[:rows] if config[:rows] if config[:filter_result] diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb index 0db058c3ab..d90e38b916 100644 --- a/lib/chef/mixin/params_validate.rb +++ b/lib/chef/mixin/params_validate.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ require "chef/constants" require "chef/property" require "chef/delayed_evaluator" +require "chef/exceptions" class Chef module Mixin @@ -332,7 +333,7 @@ class Chef def _pv_name_property(opts, key, is_name_property = true) if is_name_property if opts[key].nil? - raise CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate + raise Exceptions::CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate opts[key] = instance_variable_get(:"@name") end end @@ -404,7 +405,7 @@ class Chef passed = to_be.any? do |tb| case tb when Proc - raise CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate + raise Exceptions::CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate instance_exec(value, &tb) when Property begin @@ -448,10 +449,10 @@ class Chef # def _pv_coerce(opts, key, coercer) if opts.has_key?(key.to_s) - raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + raise Exceptions::CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate opts[key.to_s] = instance_exec(opts[key], &coercer) elsif opts.has_key?(key.to_sym) - raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + raise Exceptions::CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate opts[key.to_sym] = instance_exec(opts[key], &coercer) end end diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index 761694e010..57d1b0a4d3 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -216,16 +216,12 @@ class Chef # that precedence level, +value+ will be the symbol +:not_present+. def debug_value(*args) COMPONENTS.map do |component| - ivar = instance_variable_get(component) - value = args.inject(ivar) do |so_far, key| - if so_far == :not_present - :not_present - elsif so_far.has_key?(key) - so_far[key] - else + value = + begin + instance_variable_get(component).read!(*args) + rescue :not_present end - end [component.to_s.sub(/^@/, ""), value] end end diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb index 13a8aefe97..be9285a755 100644 --- a/lib/chef/node/immutable_collections.rb +++ b/lib/chef/node/immutable_collections.rb @@ -22,8 +22,14 @@ require "chef/node/mixin/immutablize_hash" class Chef class Node - module Immutablize + # For elements like Fixnums, true, nil... + def safe_dup(e) + e.dup + rescue TypeError + e + end + def immutablize(value) case value when Hash @@ -31,7 +37,7 @@ class Chef when Array ImmutableArray.new(value, __root__, __node__, __precedence__) else - value + safe_dup(value).freeze end end end diff --git a/lib/chef/node/mixin/immutablize_array.rb b/lib/chef/node/mixin/immutablize_array.rb index cfa7266b9a..bd330cf8a9 100644 --- a/lib/chef/node/mixin/immutablize_array.rb +++ b/lib/chef/node/mixin/immutablize_array.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright 2016, Chef Software, Inc. +# Copyright:: Copyright 2016-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/node/mixin/immutablize_hash.rb b/lib/chef/node/mixin/immutablize_hash.rb index f09e6944fc..f6b22ed7d7 100644 --- a/lib/chef/node/mixin/immutablize_hash.rb +++ b/lib/chef/node/mixin/immutablize_hash.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright 2016, Chef Software, Inc. +# Copyright:: Copyright 2016-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb index 552c90b8d1..7a1a09ae24 100644 --- a/lib/chef/node_map.rb +++ b/lib/chef/node_map.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist (<lamont@chef.io>) -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,10 +31,7 @@ class Chef # # @return [NodeMap] Returns self for possible chaining # - def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, on_platform: nil, on_platforms: nil, canonical: nil, override: nil, &block) - Chef.deprecated(:internal_api, "The on_platform option to node_map has been deprecated") if on_platform - Chef.deprecated(:internal_api, "The on_platforms option to node_map has been deprecated") if on_platforms - platform ||= on_platform || on_platforms + def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block) filters = {} filters[:platform] = platform if platform filters[:platform_version] = platform_version if platform_version diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb index 55e831c343..5dbe0bdab4 100644 --- a/lib/chef/platform/provider_mapping.rb +++ b/lib/chef/platform/provider_mapping.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,45 +26,6 @@ class Chef class Platform class << self - attr_writer :platforms - - def platforms - @platforms ||= { default: {} } - end - - include Chef::Mixin::ParamsValidate - - def find(name, version) - Chef.deprecated(:chef_platform_methods, "#{self.name}.find is deprecated") - provider_map = platforms[:default].clone - - name_sym = name - if name.kind_of?(String) - name = name.downcase - name.gsub!(/\s/, "_") - name_sym = name.to_sym - end - - if platforms.has_key?(name_sym) - platform_versions = platforms[name_sym].select { |k, v| k != :default } - if platforms[name_sym].has_key?(:default) - provider_map.merge!(platforms[name_sym][:default]) - end - platform_versions.each do |platform_version, provider| - begin - version_constraint = Chef::VersionConstraint::Platform.new(platform_version) - if version_constraint.include?(version) - Chef::Log.debug("Platform #{name} version #{version} found") - provider_map.merge!(provider) - end - rescue Chef::Exceptions::InvalidPlatformVersion - Chef::Log.debug("Chef::Version::Comparable does not know how to parse the platform version: #{version}") - end - end - end - provider_map - end - def find_platform_and_version(node) platform = nil version = nil @@ -89,134 +50,6 @@ class Chef [platform, version] end - - def provider_for_resource(resource, action = :nothing) - Chef.deprecated(:chef_platform_methods, "#{name}.provider_for_resource is deprecated") - node = resource.run_context && resource.run_context.node - raise ArgumentError, "Cannot find the provider for a resource with no run context set" unless node - provider = find_provider_for_node(node, resource).new(resource, resource.run_context) - provider.action = action - provider - end - - def provider_for_node(node, resource_type) - raise NotImplementedError, "#{name} no longer supports #provider_for_node" - end - - def find_provider_for_node(node, resource_type) - Chef.deprecated(:chef_platform_methods, "#{name}.find_provider_for_node is deprecated") - platform, version = find_platform_and_version(node) - find_provider(platform, version, resource_type) - end - - def set(args) - Chef.deprecated(:chef_platform_methods, "#{name}.set is deprecated") - validate( - args, - { - :platform => { - :kind_of => Symbol, - :required => false, - }, - :version => { - :kind_of => String, - :required => false, - }, - :resource => { - :kind_of => Symbol, - }, - :provider => { - :kind_of => [ String, Symbol, Class ], - }, - } - ) - if args.has_key?(:platform) - if args.has_key?(:version) - if platforms.has_key?(args[:platform]) - if platforms[args[:platform]].has_key?(args[:version]) - platforms[args[:platform]][args[:version]][args[:resource].to_sym] = args[:provider] - else - platforms[args[:platform]][args[:version]] = { - args[:resource].to_sym => args[:provider], - } - end - else - platforms[args[:platform]] = { - args[:version] => { - args[:resource].to_sym => args[:provider], - }, - } - end - else - if platforms.has_key?(args[:platform]) - if platforms[args[:platform]].has_key?(:default) - platforms[args[:platform]][:default][args[:resource].to_sym] = args[:provider] - elsif args[:platform] == :default - platforms[:default][args[:resource].to_sym] = args[:provider] - else - platforms[args[:platform]] = { :default => { args[:resource].to_sym => args[:provider] } } - end - else - platforms[args[:platform]] = { - :default => { - args[:resource].to_sym => args[:provider], - }, - } - end - end - else - if platforms.has_key?(:default) - platforms[:default][args[:resource].to_sym] = args[:provider] - else - platforms[:default] = { - args[:resource].to_sym => args[:provider], - } - end - end - end - - def find_provider(platform, version, resource_type) - Chef.deprecated(:chef_platform_methods, "#{name}.find_provider is deprecated") - provider_klass = explicit_provider(platform, version, resource_type) || - platform_provider(platform, version, resource_type) || - resource_matching_provider(platform, version, resource_type) - - raise Chef::Exceptions::ProviderNotFound, "Cannot find a provider for #{resource_type} on #{platform} version #{version}" if provider_klass.nil? - - provider_klass - end - - private - - def explicit_provider(platform, version, resource_type) - resource_type.kind_of?(Chef::Resource) ? resource_type.provider : nil - end - - def platform_provider(platform, version, resource_type) - pmap = Chef::Platform.find(platform, version) - rtkey = resource_type.kind_of?(Chef::Resource) ? resource_type.resource_name.to_sym : resource_type - pmap.has_key?(rtkey) ? pmap[rtkey] : nil - end - - include Chef::Mixin::ConvertToClassName - - def resource_matching_provider(platform, version, resource_type) - if resource_type.kind_of?(Chef::Resource) - class_name = if resource_type.class.name - resource_type.class.name.split("::").last - else - convert_to_class_name(resource_type.resource_name.to_s) - end - - if Chef::Provider.const_defined?(class_name, false) - Chef::Log.warn("Class Chef::Provider::#{class_name} does not declare 'provides #{convert_to_snake_case(class_name).to_sym.inspect}'.") - Chef::Log.warn("This will no longer work in Chef 13: you must use 'provides' to use the resource's DSL.") - return Chef::Provider.const_get(class_name, false) - end - end - nil - end - end end end diff --git a/lib/chef/property.rb b/lib/chef/property.rb index ac226bc815..c6f72e15a7 100644 --- a/lib/chef/property.rb +++ b/lib/chef/property.rb @@ -74,7 +74,7 @@ class Chef # return `true` if the property is set *or* if `name` is set. # @option options [Boolean] :nillable `true` opt-in to Chef-13 style behavior where # attempting to set a nil value will really set a nil value instead of issuing - # a warning and operating like a getter + # a warning and operating like a getter [DEPRECATED] # @option options [Object] :default The value this property # will return if the user does not set one. If this is `lazy`, it will # be run in the context of the instance (and able to access other @@ -264,32 +264,8 @@ class Chef # def call(resource, value = NOT_PASSED) if value == NOT_PASSED - return get(resource) - end - - if value.nil? && !nillable? - # In Chef 12, value(nil) does a *get* instead of a set, so we - # warn if the value would have been changed. In Chef 13, it will be - # equivalent to value = nil. - result = get(resource, nil_set: true) - - # Warn about this becoming a set in Chef 13. - begin - input_to_stored_value(resource, value) - # If nil is valid, and it would change the value, warn that this will change to a set. - if !result.nil? - Chef.deprecated(:custom_resource, "An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.") - end - rescue Chef::Exceptions::DeprecatedFeatureError - raise - rescue - # If nil is invalid, warn that this will become an error. - Chef.deprecated(:custom_resource, "nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}") - end - - result + get(resource) else - # Anything else, such as myprop(value) is a set set(resource, value) end end @@ -318,10 +294,11 @@ class Chef # def get(resource, nil_set: false) # If it's set, return it (and evaluate any lazy values) + value = nil + if is_set?(resource) value = get_value(resource) value = stored_value_to_output(resource, value) - else # We are getting the default value. @@ -366,13 +343,14 @@ class Chef if !value.frozen? && !value.nil? set_value(resource, value) end - - value - - elsif required? - raise Chef::Exceptions::ValidationFailed, "#{name} is required" end end + + if value.nil? && required? + raise Chef::Exceptions::ValidationFailed, "#{name} is required" + else + value + end end # @@ -391,7 +369,13 @@ class Chef # this property. # def set(resource, value) - set_value(resource, input_to_stored_value(resource, value)) + value = set_value(resource, input_to_stored_value(resource, value)) + + if value.nil? && required? + raise Chef::Exceptions::ValidationFailed, "#{name} is required" + else + value + end end # @@ -444,8 +428,8 @@ class Chef # def coerce(resource, value) if options.has_key?(:coerce) - # If we have no default value, `nil` is never coerced or validated - unless !has_default? && value.nil? + # nil is never coerced + unless value.nil? value = exec_in_resource(resource, options[:coerce], value) end end @@ -466,8 +450,8 @@ class Chef # this property. # def validate(resource, value) - # If we have no default value, `nil` is never coerced or validated - unless value.nil? && !has_default? + # nils are not validated unless we have an explicit default value + if !value.nil? || has_default? if resource resource.validate({ name => value }, { name => validation_options }) else @@ -509,12 +493,15 @@ class Chef # be using the existing getter/setter to manipulate it instead. return if !instance_variable_name - # We deprecate any attempt to create a property that already exists as a - # method in some Classes that we know would cause our users problems. - # For example, creating a `hash` property could cause issues when adding - # a Chef::Resource instance to an data structure that expects to be able - # to call the `#hash` method and get back an appropriate Fixnum. - emit_property_redefinition_deprecations + # Properties may override existing properties up the inheritance heirarchy, but + # properties must not override inherited methods like Object#hash. When the Resource is + # placed into the resource collection the ruby Hash object will call the + # Object#hash method on the resource, and overriding that with a property will cause + # very confusing results. + if property_redefines_method? + resource_name = declared_in.respond_to?(:resource_name) ? declared_in.resource_name : declared_in + raise ArgumentError, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method." + end # We prefer this form because the property name won't show up in the # stack trace if you use `define_method`. @@ -528,16 +515,6 @@ class Chef self.class.properties[#{name.inspect}].set(self, value) end EOM - rescue SyntaxError - # If the name is not a valid ruby name, we use define_method. - declared_in.define_method(name) do |value = NOT_PASSED, &block| - raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block - self.class.properties[name].call(self, value) - end - declared_in.define_method("#{name}=") do |value, &block| - raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block - self.class.properties[name].set(self, value) - end end # @@ -630,28 +607,23 @@ class Chef private - def emit_property_redefinition_deprecations + def property_redefines_method? # We only emit deprecations if this property already exists as an instance method. # Weeding out class methods avoids unnecessary deprecations such Chef::Resource # defining a `name` property when there's an already-existing `name` method # for a Module. - return unless declared_in.instance_methods.include?(name) + return false unless declared_in.instance_methods.include?(name) # Only emit deprecations for some well-known classes. This will still # allow more advanced users to subclass their own custom resources and # override their own properties. - return unless [ Object, BasicObject, Kernel, Chef::Resource ].include?(declared_in.instance_method(name).owner) + return false unless [ Object, BasicObject, Kernel, Chef::Resource ].include?(declared_in.instance_method(name).owner) # Allow top-level Chef::Resource proprties, such as `name`, to be overridden. # As of this writing, `name` is the only Chef::Resource property created with the # `property` definition, but this will allow for future properties to be extended # as needed. - return if Chef::Resource.properties.keys.include?(name) - - # Emit the deprecation. - resource_name = declared_in.respond_to?(:resource_name) ? declared_in.resource_name : declared_in - Chef.deprecated(:property_name_collision, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method. " \ - "Please use a different property name. This will raise an exception in Chef 13.") + !Chef::Resource.properties.keys.include?(name) end def exec_in_resource(resource, proc, *args) @@ -688,31 +660,9 @@ class Chef # valid. def coerce_and_validate(resource, value, is_default: false) result = coerce(resource, value) - begin - # If the input is from a default, we need to emit an invalid default warning on validate. - validate(resource, result) - rescue Chef::Exceptions::CannotValidateStaticallyError - # This one gets re-raised - raise - rescue - # Anything else is just an invalid default: in those cases, we just - # warn and return the (possibly coerced) value to the user. - if is_default - if value.nil? - Chef.deprecated(:custom_resource, "Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}") - else - Chef.deprecated(:custom_resource, "Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.") - end - else - raise - end - end + validate(resource, result) result end - - def nillable? - !!options[:nillable] - end end end diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb index 0ec441202c..bdc1114f0d 100644 --- a/lib/chef/provider.rb +++ b/lib/chef/provider.rb @@ -379,16 +379,11 @@ class Chef def action(name, &block) # We need the block directly in a method so that `super` works define_method("compile_action_#{name}", &block) - # We try hard to use `def` because define_method doesn't show the method name in the stack. - begin - class_eval <<-EOM - def action_#{name} - compile_and_converge_action { compile_action_#{name} } - end - EOM - rescue SyntaxError - define_method("action_#{name}") { send("compile_action_#{name}") } - end + class_eval <<-EOM + def action_#{name} + compile_and_converge_action { compile_action_#{name} } + end + EOM end end end diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index f7f8eaf31b..c560bed011 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -56,11 +56,13 @@ class Chef def enable_service shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance - shell_out!(default_init_command, "enable", "-s", @new_resource.service_name) + enable_flags = [ "-s", @new_resource.options ].flatten.compact + shell_out!(default_init_command, "enable", *enable_flags, @new_resource.service_name) end def disable_service - shell_out!(default_init_command, "disable", "-s", @new_resource.service_name) + disable_flags = [ "-s", @new_resource.options ].flatten.compact + shell_out!(default_init_command, "disable", *disable_flags, @new_resource.service_name) end alias_method :stop_service, :disable_service diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb index 2eb4d72ba5..439a7e9f5f 100644 --- a/lib/chef/provider_resolver.rb +++ b/lib/chef/provider_resolver.rb @@ -59,7 +59,7 @@ class Chef def resolve maybe_explicit_provider(resource) || maybe_dynamic_provider_resolution(resource, action) || - maybe_chef_platform_lookup(resource) + raise(Chef::Exceptions::ProviderNotFound, "Cannot find a provider for #{resource} on #{node["platform"]} version #{node["platform_version"]}") end # Does NOT call provides? on the resource (it is assumed this is being @@ -126,11 +126,6 @@ class Chef handler end - # try the old static lookup of providers by platform - def maybe_chef_platform_lookup(resource) - Chef::Platform.find_provider_for_node(node, resource) - end - def priority_map Chef.provider_priority_map end diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index 77d82f83ab..967703b629 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -1,7 +1,7 @@ #-- # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -104,5 +104,13 @@ class Chef run_context.node.tags.delete(tag) end end + + def to_s + "cookbook: #{cookbook_name ? cookbook_name : "(none)"}, recipe: #{recipe_name ? recipe_name : "(none)"} " + end + + def inspect + to_s + end end end diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index f8cea08076..b0e3a372e8 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -504,15 +504,6 @@ class Chef end # - # Since there are collisions with LWRP parameters named 'state' this - # method is not used by the resource_reporter and is most likely unused. - # It certainly cannot be relied upon and cannot be fixed. - # - # @deprecated - # - alias_method :state, :state_for_resource_reporter - - # # The value of the identity of this resource. # # - If there are no identity properties on the resource, `name` is returned. diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index d9f0969ecb..0231964fdf 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -18,6 +18,7 @@ # require "chef/resource" +require "shellwords" class Chef class Resource @@ -40,6 +41,7 @@ class Chef @enabled = nil @running = nil @masked = nil + @options = nil @parameters = nil @pattern = service_name @start_command = nil @@ -155,6 +157,14 @@ class Chef ) end + def options(arg = nil) + set_or_return( + :options, + arg.respond_to?(:split) ? arg.shellsplit : arg, + :kind_of => [ Array, String ] + ) + end + # Priority arguments can have two forms: # # - a simple number, in which the default start runlevels get diff --git a/lib/chef/rest.rb b/lib/chef/rest.rb deleted file mode 100644 index 0705ca9f5a..0000000000 --- a/lib/chef/rest.rb +++ /dev/null @@ -1,210 +0,0 @@ -#-- -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Thom May (<thom@clearairturbulence.org>) -# Author:: Nuo Yan (<nuo@chef.io>) -# Author:: Christopher Brown (<cb@chef.io>) -# Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2009-2016, 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 "tempfile" -require "chef/http" -class Chef - class HTTP; end - class REST < HTTP; end -end - -require "chef/http/authenticator" -require "chef/http/decompressor" -require "chef/http/json_input" -require "chef/http/json_to_model_output" -require "chef/http/cookie_manager" -require "chef/http/validate_content_length" -require "chef/config" -require "chef/exceptions" -require "chef/platform/query_helpers" -require "chef/http/remote_request_id" -require "chef/chef_class" - -class Chef - - # == Chef::REST - # Chef's custom REST client with built-in JSON support and RSA signed header - # authentication. - class REST < HTTP - - # Backwards compatibility for things that use - # Chef::REST::RESTRequest or its constants - RESTRequest = HTTP::HTTPRequest - - attr_accessor :url, :cookies, :sign_on_redirect, :redirect_limit - - attr_reader :authenticator - - # Create a REST client object. The supplied +url+ is used as the base for - # all subsequent requests. For example, when initialized with a base url - # http://localhost:4000, a call to +get_rest+ with 'nodes' will make an - # HTTP GET request to http://localhost:4000/nodes - def initialize(url, client_name = Chef::Config[:node_name], signing_key_filename = Chef::Config[:client_key], options = {}) - Chef.deprecated(:chef_rest, "Chef::REST is deprecated. Please use Chef::ServerAPI, or investigate Ridley or ChefAPI.") - - signing_key_filename = nil if chef_zero_uri?(url) - - options = options.dup - options[:client_name] = client_name - options[:signing_key_filename] = signing_key_filename - - super(url, options) - - @decompressor = Decompressor.new(options) - @authenticator = Authenticator.new(options) - @request_id = RemoteRequestID.new(options) - - @middlewares << JSONInput.new(options) - @middlewares << JSONToModelOutput.new(options) - @middlewares << CookieManager.new(options) - @middlewares << @decompressor - @middlewares << @authenticator - @middlewares << @request_id - - # ValidateContentLength should come after Decompressor - # because the order of middlewares is reversed when handling - # responses. - @middlewares << ValidateContentLength.new(options) - end - - def signing_key_filename - authenticator.signing_key_filename - end - - def auth_credentials - authenticator.auth_credentials - end - - def client_name - authenticator.client_name - end - - def signing_key - authenticator.raw_key - end - - def sign_requests? - authenticator.sign_requests? - end - - # Send an HTTP GET request to the path - # - # Using this method to +fetch+ a file is considered deprecated. - # - # === Parameters - # path:: The path to GET - # raw:: Whether you want the raw body returned, or JSON inflated. Defaults - # to JSON inflated. - def get(path, raw = false, headers = {}) - if raw - streaming_request(path, headers) - else - request(:GET, path, headers) - end - end - - alias :get_rest :get - - alias :delete_rest :delete - - alias :post_rest :post - - alias :put_rest :put - - # Streams a download to a tempfile, then yields the tempfile to a block. - # After the download, the tempfile will be closed and unlinked. - # If you rename the tempfile, it will not be deleted. - # Beware that if the server streams infinite content, this method will - # stream it until you run out of disk space. - def fetch(path, headers = {}) - streaming_request(create_url(path), headers) { |tmp_file| yield tmp_file } - end - - alias :api_request :request - - # Do a HTTP request where no middleware is loaded (e.g. JSON input/output - # conversion) but the standard Chef Authentication headers are added to the - # request. - def raw_http_request(method, path, headers, data) - url = create_url(path) - method, url, headers, data = @authenticator.handle_request(method, url, headers, data) - method, url, headers, data = @request_id.handle_request(method, url, headers, data) - response, rest_request, return_value = send_http_request(method, url, headers, data) - response.error! unless success_response?(response) - return_value - rescue Exception => exception - log_failed_request(response, return_value) unless response.nil? - - if exception.respond_to?(:chef_rest_request=) - exception.chef_rest_request = rest_request - end - raise - end - - # Deprecated: - # Responsibilities of this method have been split up. The #http_client is - # now responsible for making individual requests, while - # #retrying_http_errors handles error/retry logic. - def retriable_http_request(method, url, req_body, headers) - rest_request = Chef::HTTP::HTTPRequest.new(method, url, req_body, headers) - - Chef::Log.debug("Sending HTTP request via #{method} to #{url.host}:#{url.port}#{rest_request.path}") - - retrying_http_errors(url) do - yield rest_request - end - end - - # Customized streaming behavior; sets the accepted content type to "*/*" - # if not otherwise specified for compatibility purposes - def streaming_request(url, headers, &block) - headers["Accept"] ||= "*/*" - super - end - - alias :retriable_rest_request :retriable_http_request - - def follow_redirect - unless @sign_on_redirect - @authenticator.sign_request = false - end - super - ensure - @authenticator.sign_request = true - end - - public :create_url - - ############################################################################ - # DEPRECATED - ############################################################################ - - def decompress_body(body) - @decompressor.decompress_body(body) - end - - def authentication_headers(method, url, json_body = nil) - authenticator.authentication_headers(method, url, json_body) - end - - end -end diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 6d84b7773d..a606585e80 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Tim Hinderliter (<tim@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -576,27 +576,6 @@ ERROR_MESSAGE attr_reader :loaded_attributes_hash attr_reader :loaded_recipes_hash - module Deprecated - ### - # These need to be settable so deploy can run a resource_collection - # independent of any cookbooks via +recipe_eval+ - def audits=(value) - Chef.deprecated(:internal_api, "Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") - @audits = value - end - - def immediate_notification_collection=(value) - Chef.deprecated(:internal_api, "Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") - @immediate_notification_collection = value - end - - def delayed_notification_collection=(value) - Chef.deprecated(:internal_api, "Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") - @delayed_notification_collection = value - end - end - prepend Deprecated - # # A child run context. Delegates all root context calls to its parent. # diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb index fb77238ced..7357dbf6be 100644 --- a/lib/chef/search/query.rb +++ b/lib/chef/search/query.rb @@ -106,10 +106,12 @@ class Chef return args.first if args.first.is_a?(Hash) args_h = Hash.new - args_h[:sort] = args[0] if args[0] - args_h[:start] = args[1] if args[1] - args_h[:rows] = args[2] - args_h[:filter_result] = args[3] + # If we have 4 arguments, the first is the now-removed sort option, so + # just ignore it. + args.pop(0) if args.length == 4 + args_h[:start] = args[0] if args[0] + args_h[:rows] = args[1] + args_h[:filter_result] = args[2] args_h end @@ -119,16 +121,15 @@ class Chef s && Addressable::URI.encode_component(s.to_s, QUERY_PARAM_VALUE) end - def create_query_string(type, query, rows, start, sort) + def create_query_string(type, query, rows, start) qstr = "search/#{type}?q=#{escape_value(query)}" - qstr += "&sort=#{escape_value(sort)}" if sort qstr += "&start=#{escape_value(start)}" if start qstr += "&rows=#{escape_value(rows)}" if rows qstr end - def call_rest_service(type, query: "*:*", rows: nil, start: 0, sort: "X_CHEF_id_CHEF_X asc", filter_result: nil) - query_string = create_query_string(type, query, rows, start, sort) + def call_rest_service(type, query: "*:*", rows: nil, start: 0, filter_result: nil) + query_string = create_query_string(type, query, rows, start) if filter_result response = rest.post(query_string, filter_result) diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb index e8c3704553..b4c0277c57 100644 --- a/lib/chef/shell.rb +++ b/lib/chef/shell.rb @@ -27,6 +27,7 @@ require "chef/config" require "chef/config_fetcher" require "chef/shell/shell_session" +require "chef/workstation_config_loader" require "chef/shell/ext" require "chef/json_compat" require "chef/util/path_helper" @@ -62,6 +63,12 @@ module Shell irb = IRB::Irb.new + if solo_mode? + # Setup the mocked ChefServer + Chef::Config.local_mode = true + Chef::LocalMode.setup_server_connectivity + end + init(irb.context.main) irb_conf[:IRB_RC].call(irb.context) if irb_conf[:IRB_RC] @@ -74,6 +81,13 @@ module Shell catch(:IRB_EXIT) do irb.eval_input end + ensure + # We destroy the mocked ChefServer + Chef::LocalMode.destroy_server_connectivity if solo_mode? + end + + def self.solo_mode? + Chef::Config[:solo] end def self.setup_logger @@ -167,8 +181,9 @@ module Shell def self.client_type type = Shell::StandAloneSession - type = Shell::SoloSession if Chef::Config[:shell_solo] - type = Shell::ClientSession if Chef::Config[:client] + type = Shell::SoloSession if solo_mode? + type = Shell::SoloLegacySession if Chef::Config[:solo_legacy_shell] + type = Shell::ClientSession if Chef::Config[:client] type = Shell::DoppelGangerSession if Chef::Config[:doppelganger] type end @@ -196,8 +211,10 @@ module Shell When no CONFIG is specified, chef-shell attempts to load a default configuration file: * If a NAMED_CONF is given, chef-shell will load ~/.chef/NAMED_CONF/chef_shell.rb * If no NAMED_CONF is given chef-shell will load ~/.chef/chef_shell.rb if it exists -* chef-shell falls back to loading /etc/chef/client.rb or /etc/chef/solo.rb if -z or - -s options are given and no chef_shell.rb can be found. +* If no chef_shell.rb can be found, chef-shell falls back to load: + /etc/chef/client.rb if -z option is given. + /etc/chef/solo.rb if --solo-legacy-mode option is given. + .chef/knife.rb if -s option is given. FOOTER option :config_file, @@ -226,7 +243,7 @@ FOOTER :default => true, :boolean => true - option :shell_solo, + option :solo_shell, :short => "-s", :long => "--solo", :description => "chef-solo session", @@ -239,6 +256,12 @@ FOOTER :description => "chef-client session", :boolean => true + option :solo_legacy_shell, + :long => "--solo-legacy-mode", + :description => "chef-solo legacy session", + :boolean => true, + :proc => proc { Chef::Config[:solo_legacy_mode] = true } + option :json_attribs, :short => "-j JSON_ATTRIBS", :long => "--json-attributes JSON_ATTRIBS", @@ -313,10 +336,12 @@ FOOTER config_file_to_try elsif dot_chef_dir && ::File.exist?(File.join(dot_chef_dir, "chef_shell.rb")) File.join(dot_chef_dir, "chef_shell.rb") - elsif config[:solo] + elsif config[:solo_legacy_shell] Chef::Config.platform_specific_path("/etc/chef/solo.rb") elsif config[:client] Chef::Config.platform_specific_path("/etc/chef/client.rb") + elsif config[:solo_shell] + Chef::WorkstationConfigLoader.new(nil, Chef::Log).config_location else nil end diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb index 3034e1cf5d..41d5bd64a0 100644 --- a/lib/chef/shell/shell_session.rb +++ b/lib/chef/shell/shell_session.rb @@ -159,9 +159,9 @@ module Shell end - class SoloSession < ShellSession + class SoloLegacySession < ShellSession - session_type :solo + session_type :solo_legacy_mode def definitions @run_context.definitions @@ -191,10 +191,14 @@ module Shell end - class ClientSession < SoloSession + class ClientSession < ShellSession session_type :client + def definitions + @run_context.definitions + end + def save_node @client.save_node end @@ -223,6 +227,12 @@ module Shell end + class SoloSession < ClientSession + + session_type :solo + + end + class DoppelGangerClient < Chef::Client attr_reader :node_name diff --git a/lib/chef/shell_out.rb b/lib/chef/shell_out.rb deleted file mode 100644 index 54ff718e8e..0000000000 --- a/lib/chef/shell_out.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "mixlib/shellout" - -class Chef - class ShellOut < Mixlib::ShellOut - - def initialize(*args) - Chef::Log.warn("Chef::ShellOut is deprecated, please use Mixlib::ShellOut") - called_from = caller[0..3].inject("Called from:\n") { |msg, trace_line| msg << " #{trace_line}\n" } - Chef::Log.warn(called_from) - super - end - end -end diff --git a/lib/chef/tasks/chef_repo.rake b/lib/chef/tasks/chef_repo.rake deleted file mode 100644 index 543bd8d864..0000000000 --- a/lib/chef/tasks/chef_repo.rake +++ /dev/null @@ -1,200 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. -# Copyright:: Copyright 2014-2016, 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. -# -TOPDIR = "." -require "rake" - -desc "By default, print deprecation notice" -task :default do - puts deprecation_notice -end - -desc "Install the latest copy of the repository on this Chef Server" -task :install do - puts deprecation_notice - puts "The `install` rake task, which included the `update`, `roles`, and" - puts "`upload_cookbooks` rake tasks is replaced by the `knife upload`" - puts 'sub-command. The notion of "installing" the chef-repo to the Chef' - puts "Server. Previously the `install` task would manage server and" - puts "client configuration. This will not work at all on Chef Server 11+" - puts "and client configuration should be managed with the `chef-client`" - puts "cookbook." -end - -desc "Update your repository from source control" -task :update do - puts deprecation_notice - puts "The `update` rake task previously updated the chef-repo from" - puts "the detected version control system, either svn or git. However," - puts "it has not been recommended for users for years. Most users in" - puts "the community use `git`, so the Subversion functionality is not" - puts "required, and `git pull` is sufficient for many workflows. The" - puts "world of git workflows is rather different now than it was when" - puts "this rake task was created." -end - -desc "Create a new cookbook (with COOKBOOK=name, optional CB_PREFIX=site-)" -task :new_cookbook do - cb = ENV["COOKBOOK"] || "my_cookbook_name" - puts deprecation_notice - puts "The `new_cookbook` rake task is replaced by the ChefDK cookbook" - puts "generator. To generate a new cookbook run:" - puts - puts "chef generate cookbook #{ENV['COOKBOOK']}" - puts - puts "Or, if you are not using ChefDK, use `knife cookbook create`:" - puts - puts "knife cookbook create #{ENV['COOKBOOK']}" -end - -desc "Create a new self-signed SSL certificate for FQDN=foo.example.com" -task :ssl_cert do - puts deprecation_notice - puts "The `ssl_cert` rake task is superseded by using the CHEF-maintained" - puts '`openssl` cookbook\'s `openssl_x509` resource which can generate' - puts "self-signed certificate chains as convergent resources." - puts - puts "https://supermarket.getchef.com/cookbooks/openssl" -end - -desc "Build cookbook metadata.json from metadata.rb" -task :metadata do - puts deprecation_notice - puts "The `metadata` rake task is not recommended. Cookbook" - puts "`metadata.json` is automatically generated from `metadata.rb`" - puts "by `knife` when uploading cookbooks to the Chef Server." -end - -desc "Update roles" -task :roles do - puts deprecation_notice - puts "The `roles` rake task is not recommended. If you are using Ruby" - puts "role files (roles/*.rb), you can upload them all with:" - puts - puts "knife role from file roles/*" - puts - puts "If you are using JSON role files (roles/*.json), you can upload" - puts "them all with:" - puts - puts "knife upload roles/*.json" -end - -desc "Update a specific role" -task :role do - puts deprecation_notice - puts "The `role` rake task is not recommended. If you are using Ruby" - puts "role files, you can upload a single role with:" - puts - puts "knife role from file rolename.rb" - puts - puts "If you are using JSON role files, you can upload a single role with" - puts - puts "knife upload roles/rolename.json" -end - -desc "Upload all cookbooks" -task :upload_cookbooks do - puts deprecation_notice - puts deprecated_cookbook_upload -end - -desc "Upload a single cookbook" -task :upload_cookbook do - puts deprecation_notice - puts deprecated_cookbook_upload -end - -desc "Test all cookbooks" -task :test_cookbooks do - puts deprecation_notice - puts "The `test_cookbooks` rake task is no longer recommended. Previously" - puts "it only performed a syntax check, and did no other kind of testing," - puts "and the Chef Community has a rich ecosystem of testing tools for" - puts "various purposes:" - puts - puts "- knife cookbook test will perform a syntax check, as this task did" - puts " before." - puts "- rubocop and foodcritic will perform lint checking for Ruby and" - puts " Chef cookbook style according to community standards." - puts "- ChefSpec will perform unit testing" - puts "- Test Kitchen will perform convergence and post-convergence" - puts " testing on virtual machines." -end - -desc "Test a single cookbook" -task :test_cookbook => [:test_cookbooks] - -namespace :databag do - desc "Upload a single databag" - task :upload do - puts deprecation_notice - puts "The `data_bags:upload` task is not recommended. You should use" - puts "the `knife upload` sub-command for uploading data bag items." - puts - puts "knife upload data_bags/bagname/itemname.json" - end - - desc "Upload all databags" - task :upload_all do - puts deprecation_notice - puts "The `data_bags:upload_all` task is not recommended. You should" - puts "use the `knife upload` sub-command for uploading data bag items." - puts - puts "knife upload data_bags/*" - end - - desc "Create a databag" - task :create do - puts deprecation_notice - puts deprecated_data_bag_creation - end - - desc "Create a databag item stub" - task :create_item do - puts deprecation_notice - puts deprecated_data_bag_creation - end -end - -def deprecation_notice - %Q{************************************************* -NOTICE: Chef Repository Rake Tasks Are Deprecated -************************************************* -} -end - -def deprecated_cookbook_upload - %Q{ -The `upload_cookbook` and `upload_cookbooks` rake tasks are not -recommended. These tasks are replaced by other, better workflow -tools, such as `knife cookbook upload`, `knife upload`, or `berks` -} -end - -def deprecated_data_bag_creation - %Q{ -The `data_bags:create` and `data_bags:create_item` tasks are not -recommended. You should create data bag items as JSON files in the data_bags -directory, with a sub-directory for each bag, and use `knife upload` to -upload them. For example, if you have a data bags named `users`, with -`finn`, and `jake` items, you would have: - -./data_bags/users/finn.json -./data-bags/users/jake.json -} -end diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index f9f8f011af..059a04d59a 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -112,7 +112,7 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows def add(args) transformed_args = transform_usri3(args) NetUser.net_user_add_l3(nil, transformed_args) - NetUser.net_local_group_add_member(nil, "Users", args[:name]) + NetUser.net_local_group_add_member(nil, Chef::ReservedNames::Win32::Security::SID.BuiltinUsers.account_simple_name, args[:name]) end # FIXME: yard with @yield diff --git a/lib/chef/version.rb b/lib/chef/version.rb index 02690cc650..67f2c57adb 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -21,7 +21,7 @@ class Chef CHEF_ROOT = File.expand_path("../..", __FILE__) - VERSION = "13.0.43" + VERSION = "13.0.63" end # diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb index 983166ac70..c77616853c 100644 --- a/lib/chef/win32/security/sid.rb +++ b/lib/chef/win32/security/sid.rb @@ -59,6 +59,11 @@ class Chef Chef::ReservedNames::Win32::Security.lookup_account_sid(self) end + def account_simple_name + domain, name, use = account + name + end + def account_name domain, name, use = account (!domain.nil? && domain.length > 0) ? "#{domain}\\#{name}" : name diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock index 20eb83adec..04324ad1e6 100644 --- a/omnibus/Gemfile.lock +++ b/omnibus/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/chef/license_scout - revision: 83f16f6bbf7f0f9ef94cf694aea2881e65ee034c + revision: 544a9335549148037a4161ff4c6c9d9a71e39660 specs: license_scout (0.1.2) ffi-yajl (~> 2.2) @@ -8,7 +8,7 @@ GIT GIT remote: https://github.com/chef/omnibus - revision: 76d907f4fe92a28c5f7ab11779341e1d773c358d + revision: 443f42abe0b791b132fb27aa85448bb691af9102 specs: omnibus (5.5.0) aws-sdk (~> 2) @@ -19,6 +19,7 @@ GIT mixlib-shellout (~> 2.0) mixlib-versioning ohai (~> 8.0) + pedump ruby-progressbar (~> 1.7) thor (~> 0.18) @@ -37,13 +38,13 @@ GEM public_suffix (~> 2.0, >= 2.0.2) artifactory (2.7.0) awesome_print (1.7.0) - aws-sdk (2.8.5) - aws-sdk-resources (= 2.8.5) - aws-sdk-core (2.8.5) + aws-sdk (2.8.7) + aws-sdk-resources (= 2.8.7) + aws-sdk-core (2.8.7) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-resources (2.8.5) - aws-sdk-core (= 2.8.5) + aws-sdk-resources (2.8.7) + aws-sdk-core (= 2.8.7) aws-sigv4 (1.0.0) berkshelf (4.3.5) addressable (~> 2.3, >= 2.3.4) diff --git a/spec/data/shef-config.rb b/spec/data/shef-config.rb index 02d3610e55..efd601d6d8 100644 --- a/spec/data/shef-config.rb +++ b/spec/data/shef-config.rb @@ -7,3 +7,5 @@ ohai[:disabled_plugins] << "solaris2::cpu" << "solaris2::dmi" << "solaris2::file ohai[:disabled_plugins] << "solaris2::virtualization" << "solaris2::zpools" ohai[:disabled_plugins] << "c" << "php" << "mono" << "groovy" << "lua" << "erlang" ohai[:disabled_plugins] << "kernel" << "linux::filesystem" << "ruby" +chef_repo_path File.dirname(__FILE__) +cookbook_path "#{chef_repo_path}/cookbooks" diff --git a/spec/functional/knife/ssh_spec.rb b/spec/functional/knife/ssh_spec.rb index dbd7b92c6c..fba344649f 100644 --- a/spec/functional/knife/ssh_spec.rb +++ b/spec/functional/knife/ssh_spec.rb @@ -304,7 +304,7 @@ describe Chef::Knife::Ssh do Chef::Config[:client_key] = nil Chef::Config[:chef_server_url] = "http://localhost:9000" - @api.post("/search/node?q=*:*&sort=X_CHEF_id_CHEF_X%20asc&start=0", 200) do + @api.post("/search/node?q=*:*&start=0", 200) do %({"total":1, "start":0, "rows":[{"data": {"fqdn":"the.fqdn", "config": "the_public_hostname", "knife_config": "the_public_hostname" }}]}) end end diff --git a/spec/functional/rest_spec.rb b/spec/functional/rest_spec.rb deleted file mode 100644 index 14e76087c4..0000000000 --- a/spec/functional/rest_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ -# -# Author:: Lamont Granquist (<lamont@chef.io>) -# Copyright:: Copyright 2014-2016, 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 "spec_helper" -require "tiny_server" -require "support/shared/functional/http" - -describe Chef::REST do - include ChefHTTPShared - - let(:http_client) { described_class.new(source) } - let(:http_client_disable_gzip) { described_class.new(source, Chef::Config[:node_name], Chef::Config[:client_key], { :disable_gzip => true } ) } - - shared_examples_for "downloads requests correctly" do - it "successfully downloads a streaming request" do - tempfile = http_client.streaming_request(source, {}) - tempfile.close - expect(Digest::MD5.hexdigest(binread(tempfile.path))).to eq(Digest::MD5.hexdigest(expected_content)) - end - - it "successfully downloads a GET request" do - tempfile = http_client.get(source, {}) - tempfile.close - expect(Digest::MD5.hexdigest(binread(tempfile.path))).to eq(Digest::MD5.hexdigest(expected_content)) - end - end - - shared_examples_for "validates content length and throws an exception" do - it "fails validation on a streaming download" do - expect { http_client.streaming_request(source, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - - it "fails validation on a GET request" do - expect { http_client.get(source, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - end - - shared_examples_for "an endpoint that 403s" do - it "fails with a Net::HTTPServerException on a streaming download" do - expect { http_client.streaming_request(source, {}) }.to raise_error(Net::HTTPServerException) - end - - it "fails with a Net::HTTPServerException on a GET request" do - expect { http_client.get(source, {}) }.to raise_error(Net::HTTPServerException) - end - end - - # see CHEF-5100 - shared_examples_for "a 403 after a successful request when reusing the request object" do - it "fails with a Net::HTTPServerException on a streaming download" do - tempfile = http_client.streaming_request(source, {}) - tempfile.close - expect(Digest::MD5.hexdigest(binread(tempfile.path))).to eq(Digest::MD5.hexdigest(expected_content)) - expect { http_client.streaming_request(source2, {}) }.to raise_error(Net::HTTPServerException) - end - - it "fails with a Net::HTTPServerException on a GET request" do - tempfile = http_client.get(source, {}) - tempfile.close - expect(Digest::MD5.hexdigest(binread(tempfile.path))).to eq(Digest::MD5.hexdigest(expected_content)) - expect { http_client.get(source2, {}) }.to raise_error(Net::HTTPServerException) - end - end - - before do - Chef::Config[:node_name] = "webmonkey.example.com" - Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" - Chef::Config[:treat_deprecation_warnings_as_errors] = false - end - - before(:each) do - start_tiny_server - end - - after(:each) do - stop_tiny_server - end - - it_behaves_like "downloading all the things" -end diff --git a/spec/functional/shell_spec.rb b/spec/functional/shell_spec.rb index 636162fb16..8c8d7ba482 100644 --- a/spec/functional/shell_spec.rb +++ b/spec/functional/shell_spec.rb @@ -135,6 +135,24 @@ describe Shell do expect(exitstatus).to eq(0) end + context "on solo mode" do + it "starts correctly" do + output, exitstatus = run_chef_shell_with("--solo") + expect(output).to include("done") + expect(exitstatus).to eq(0) + end + + it "should be able to use the API" do + output, exitstatus = run_chef_shell_with("-s") do |out, keyboard| + simple_api_get = "api.get('data')" + keyboard.puts(simple_api_get) + read_until(out, simple_api_get) + end + expect(output).to include("{}") + expect(exitstatus).to eq(0) + end + end + it "sets the override_runlist from the command line" do output, exitstatus = run_chef_shell_with("-o 'override::foo,override::bar'") do |out, keyboard| show_recipes_code = %q[puts "#{node["recipes"].inspect}"] diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb index 7a8059066a..2a31638c0f 100644 --- a/spec/integration/client/client_spec.rb +++ b/spec/integration/client/client_spec.rb @@ -388,18 +388,8 @@ EOM when_the_repository "has a cookbook that generates deprecation warnings" do before do file "cookbooks/x/recipes/default.rb", <<-EOM - class ::MyResource < Chef::Resource - use_automatic_resource_name - property :x, default: [] - property :y, default: {} - end - - my_resource 'blah' do - 1.upto(10) do - x nil - end - x nil - end + Chef.deprecated(:internal_api, "Test deprecation") + Chef.deprecated(:internal_api, "Test deprecation") EOM end @@ -432,7 +422,7 @@ EOM expect(run_complete).to be >= 0 # Make sure there is exactly one result for each, and that it occurs *after* the complete message. - expect(match_indices(/An attempt was made to change x from \[\] to nil by calling x\(nil\). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil./, result.stdout)).to match([ be > run_complete ]) + expect(match_indices(/Test deprecation/, result.stdout)).to match([ be > run_complete ]) end end diff --git a/spec/integration/recipes/recipe_dsl_spec.rb b/spec/integration/recipes/recipe_dsl_spec.rb index e2fa7df1fc..32283393ce 100644 --- a/spec/integration/recipes/recipe_dsl_spec.rb +++ b/spec/integration/recipes/recipe_dsl_spec.rb @@ -81,52 +81,6 @@ describe "Recipe DSL methods" do Chef::Config[:treat_deprecation_warnings_as_errors] = false end - context "with a resource 'backcompat_thingy' declared in Chef::Resource and Chef::Provider" do - before(:context) do - - class Chef::Resource::BackcompatThingy < Chef::Resource - default_action :create - end - class Chef::Provider::BackcompatThingy < Chef::Provider - def load_current_resource - end - - def action_create - BaseThingy.created_resource = new_resource.class - BaseThingy.created_provider = self.class - end - end - - end - - it "backcompat_thingy creates a Chef::Resource::BackcompatThingy" do - recipe = converge do - backcompat_thingy("blah") {} - end - expect(BaseThingy.created_resource).to eq Chef::Resource::BackcompatThingy - expect(BaseThingy.created_provider).to eq Chef::Provider::BackcompatThingy - end - - context "and another resource 'backcompat_thingy' in BackcompatThingy with 'provides'" do - before(:context) do - - class RecipeDSLSpecNamespace::BackcompatThingy < BaseThingy - provides :backcompat_thingy - resource_name :backcompat_thingy - end - - end - - it "backcompat_thingy creates a BackcompatThingy" do - recipe = converge do - backcompat_thingy("blah") {} - end - expect(recipe.logged_warnings).to match(/Class Chef::Provider::BackcompatThingy does not declare 'provides :backcompat_thingy'./) - expect(BaseThingy.created_resource).not_to be_nil - end - end - end - context "with a resource named RecipeDSLSpecNamespace::Bar::BarThingy" do before(:context) do @@ -1220,35 +1174,6 @@ describe "Recipe DSL methods" do end end - context "with provides? returning true to blarghle_blarghle_little_star and not resource_name" do - before do - temp_blarghle_blarghle_little_star = blarghle_blarghle_little_star - resource_class.define_singleton_method(:provides?) do |node, resource_name| - @called_provides = true - resource_name == temp_blarghle_blarghle_little_star - end - end - - it "my_resource does not return the resource" do - dsl_name = my_resource - expect_converge do - instance_eval("#{dsl_name} 'foo'") - end.to raise_error(Chef::Exceptions::NoSuchResourceType) - expect(resource_class.called_provides).to be_truthy - end - - it "blarghle_blarghle_little_star 'foo' returns the resource and emits a warning" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - dsl_name = blarghle_blarghle_little_star - recipe = converge do - instance_eval("#{dsl_name} 'foo'") - end - expect(recipe.logged_warnings).to include "WARN: #{resource_class}.provides? returned true when asked if it provides DSL #{dsl_name}, but provides :#{dsl_name} was never called!" - expect(BaseThingy.created_resource).to eq resource_class - expect(resource_class.called_provides).to be_truthy - end - end - context "and a provider" do let(:provider_class) do Class.new(BaseThingy::Provider) do @@ -1448,6 +1373,23 @@ describe "Recipe DSL methods" do end end end + + context "with UTF-8 provides" do + before(:context) do + class UTF8Thingy < BaseThingy + resource_name :Straße + provides :Straße + end + end + + it "utf-8 dsl names work" do + recipe = converge do + Straße("blah") {} + end + expect(recipe.logged_warnings).to eq "" + expect(BaseThingy.created_resource).to eq(UTF8Thingy) + end + end end before(:all) { Namer.current_index = 0 } @@ -1494,30 +1436,4 @@ describe "Recipe DSL methods" do end end - context "with a dynamically defined resource and regular provider" do - before(:context) do - Class.new(Chef::Resource) do - resource_name :lw_resource_with_hw_provider_test_case - default_action :create - attr_accessor :created_provider - end - class Chef::Provider::LwResourceWithHwProviderTestCase < Chef::Provider - def load_current_resource - end - - def action_create - new_resource.created_provider = self.class - end - end - end - - it "looks up the provider in Chef::Provider converting the resource name from snake case to camel case" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource = nil - recipe = converge do - resource = lw_resource_with_hw_provider_test_case("blah") {} - end - expect(resource.created_provider).to eq(Chef::Provider::LwResourceWithHwProviderTestCase) - end - end end diff --git a/spec/integration/recipes/resource_action_spec.rb b/spec/integration/recipes/resource_action_spec.rb index f11696bae4..7a68164d41 100644 --- a/spec/integration/recipes/resource_action_spec.rb +++ b/spec/integration/recipes/resource_action_spec.rb @@ -357,7 +357,7 @@ module ResourceActionSpec end end - context "With a resource with action a-b-c d" do + context "With a resource with a UTF-8 action" do class WeirdActionJackson < Chef::Resource use_automatic_resource_name @@ -365,7 +365,7 @@ module ResourceActionSpec attr_accessor :action_was end - action "a-b-c d" do + action :Straße do WeirdActionJackson.action_was = action end end @@ -374,7 +374,7 @@ module ResourceActionSpec expect_recipe do weird_action_jackson "hi" end.to be_up_to_date - expect(WeirdActionJackson.action_was).to eq :"a-b-c d" + expect(WeirdActionJackson.action_was).to eq :Straße end end diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index 0869b83e43..cf8d4d4a4f 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -208,7 +208,7 @@ describe Chef::Node::Attribute do end describe "when debugging attributes" do - before do + it "gives the value at each level of precedence for a path spec" do @attributes.default[:foo][:bar] = "default" @attributes.env_default[:foo][:bar] = "env_default" @attributes.role_default[:foo][:bar] = "role_default" @@ -219,9 +219,7 @@ describe Chef::Node::Attribute do @attributes.env_override[:foo][:bar] = "env_override" @attributes.force_override[:foo][:bar] = "force_override" @attributes.automatic[:foo][:bar] = "automatic" - end - it "gives the value at each level of precedence for a path spec" do expected = [ %w{default default}, %w{env_default env_default}, @@ -236,6 +234,25 @@ describe Chef::Node::Attribute do ] expect(@attributes.debug_value(:foo, :bar)).to eq(expected) end + + it "works through arrays" do + @attributes.default["foo"] = [ { "bar" => "baz" } ] + + expect(@attributes.debug_value(:foo, 0)).to eq( + [ + ["default", { "bar" => "baz" }], + ["env_default", :not_present], + ["role_default", :not_present], + ["force_default", :not_present], + ["normal", :not_present], + ["override", :not_present], + ["role_override", :not_present], + ["env_override", :not_present], + ["force_override", :not_present], + ["automatic", :not_present], + ] + ) + end end describe "when fetching values based on precedence" do @@ -1244,4 +1261,16 @@ describe Chef::Node::Attribute do @attributes.default["foo"]["bar"]["baz"] = "quux" end end + + describe "frozen immutable strings" do + it "strings in hashes should be frozen" do + @attributes.default["foo"]["bar"]["baz"] = "fizz" + expect { @attributes["foo"]["bar"]["baz"] << "buzz" }.to raise_error(RuntimeError, "can't modify frozen String") + end + + it "strings in arrays should be frozen" do + @attributes.default["foo"]["bar"] = [ "fizz" ] + expect { @attributes["foo"]["bar"][0] << "buzz" }.to raise_error(RuntimeError, "can't modify frozen String") + end + end end diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb index 0480a721af..822f689eab 100644 --- a/spec/unit/node_map_spec.rb +++ b/spec/unit/node_map_spec.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist (<lamont@chef.io>) -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -145,26 +145,4 @@ describe Chef::NodeMap do end end - describe "resource back-compat testing" do - before :each do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - end - - it "should handle :on_platforms => :all" do - node_map.set(:chef_gem, :foo, :on_platforms => :all) - allow(node).to receive(:[]).with(:platform).and_return("windows") - expect(node_map.get(node, :chef_gem)).to eql(:foo) - end - it "should handle :on_platforms => [ 'windows' ]" do - node_map.set(:dsc_script, :foo, :on_platforms => [ "windows" ]) - allow(node).to receive(:[]).with(:platform).and_return("windows") - expect(node_map.get(node, :dsc_script)).to eql(:foo) - end - it "should handle :on_platform => :all" do - node_map.set(:link, :foo, :on_platform => :all) - allow(node).to receive(:[]).with(:platform).and_return("windows") - expect(node_map.get(node, :link)).to eql(:foo) - end - end - end diff --git a/spec/unit/platform_spec.rb b/spec/unit/platform_spec.rb deleted file mode 100644 index 3a562d3ce6..0000000000 --- a/spec/unit/platform_spec.rb +++ /dev/null @@ -1,269 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, 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 "spec_helper" - -describe Chef::Platform do - - context "while testing with fake data" do - def expect_platform_warning(method_name, times: 1, recurse: true) - expect(Chef).to receive(:deprecated).with(:chef_platform_methods, "Chef::Platform.#{method_name} is deprecated").exactly(times).times - return unless recurse - - expect_platform_warning(:find_provider_for_node, times: times) if method_name == :provider_for_resource - expect_platform_warning(:find_provider, times: times) if method_name == :find_provider_for_node - expect_platform_warning(:find, times: times) if method_name == :find_provider - end - - before :all do - @original_platform_map = Chef::Platform.platforms - end - - after :all do || - Chef::Platform.platforms = @original_platform_map - end - - before(:each) do - Chef::Platform.platforms = { - :darwin => { - ">= 10.11" => { - :file => "new_darwinian", - }, - "9.2.2" => { - :file => "darwinian", - :else => "thing", - }, - :default => { - :file => "old school", - :snicker => "snack", - }, - }, - :mars_volta => { - }, - :default => { - :file => Chef::Provider::File, - :pax => "brittania", - :cat => "nice", - }, - } - @events = Chef::EventDispatch::Dispatcher.new - end - - it "should allow you to look up a platform by name and version, returning the provider map for it" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("Darwin", "9.2.2") - expect(pmap).to be_a_kind_of(Hash) - expect(pmap[:file]).to eql("darwinian") - end - - it "should allow you to look up a platform by name and version using \"greater than\" style operators" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("Darwin", "11.1.0") - expect(pmap).to be_a_kind_of(Hash) - expect(pmap[:file]).to eql("new_darwinian") - end - - it "should use the default providers for an os if the specific version does not exist" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("Darwin", "1") - expect(pmap).to be_a_kind_of(Hash) - expect(pmap[:file]).to eql("old school") - end - - it "should use the default providers if the os doesn't give me a default, but does exist" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("mars_volta", "1") - expect(pmap).to be_a_kind_of(Hash) - expect(pmap[:file]).to eql(Chef::Provider::File) - end - - it "should use the default provider if the os does not exist" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("AIX", "1") - expect(pmap).to be_a_kind_of(Hash) - expect(pmap[:file]).to eql(Chef::Provider::File) - end - - it "should merge the defaults for an os with the specific version" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("Darwin", "9.2.2") - expect(pmap[:file]).to eql("darwinian") - expect(pmap[:snicker]).to eql("snack") - end - - it "should merge the defaults for an os with the universal defaults" do - expect_platform_warning(:find) - pmap = Chef::Platform.find("Darwin", "9.2.2") - expect(pmap[:file]).to eql("darwinian") - expect(pmap[:pax]).to eql("brittania") - end - - it "should allow you to look up a provider for a platform directly by symbol" do - expect_platform_warning(:find_provider) - expect(Chef::Platform.find_provider("Darwin", "9.2.2", :file)).to eql("darwinian") - end - - it "should raise an exception if a provider cannot be found for a resource type" do - expect_platform_warning(:find_provider) - expect { Chef::Platform.find_provider("Darwin", "9.2.2", :coffee) }.to raise_error(Chef::Exceptions::ProviderNotFound) - end - - it "should look up a provider for a resource with a Chef::Resource object" do - kitty = Chef::Resource::Cat.new("loulou") - expect_platform_warning(:find_provider) - expect(Chef::Platform.find_provider("Darwin", "9.2.2", kitty)).to eql("nice") - end - - it "should look up a provider with a node and a Chef::Resource object" do - kitty = Chef::Resource::Cat.new("loulou") - node = Chef::Node.new - node.name("Intel") - node.automatic_attrs[:platform] = "mac_os_x" - node.automatic_attrs[:platform_version] = "9.2.2" - expect_platform_warning(:find_provider_for_node) - expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql("nice") - end - - it "should not throw an exception when the platform version has an unknown format" do - expect_platform_warning(:find_provider) - expect(Chef::Platform.find_provider(:darwin, "bad-version", :file)).to eql("old school") - end - - it "should prefer an explicit provider" do - kitty = Chef::Resource::Cat.new("loulou") - allow(kitty).to receive(:provider).and_return(Chef::Provider::File) - node = Chef::Node.new - node.name("Intel") - node.automatic_attrs[:platform] = "mac_os_x" - node.automatic_attrs[:platform_version] = "9.2.2" - expect_platform_warning(:find_provider_for_node, recurse: false) - expect_platform_warning(:find_provider, recurse: false) - expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql(Chef::Provider::File) - end - - it "should look up a provider based on the resource name if nothing else matches" do - kitty = Chef::Resource::Cat.new("loulou") - class Chef::Provider::Cat < Chef::Provider; end - Chef::Platform.platforms[:default].delete(:cat) - node = Chef::Node.new - node.name("Intel") - node.automatic_attrs[:platform] = "mac_os_x" - node.automatic_attrs[:platform_version] = "8.5" - expect_platform_warning(:find_provider_for_node) - expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql(Chef::Provider::Cat) - end - - def setup_file_resource - node = Chef::Node.new - node.automatic_attrs[:platform] = "mac_os_x" - node.automatic_attrs[:platform_version] = "9.2.2" - run_context = Chef::RunContext.new(node, {}, @events) - [ Chef::Resource::File.new("whateva", run_context), run_context ] - end - - it "returns a provider object given a Chef::Resource object which has a valid run context and an action" do - file, run_context = setup_file_resource - expect_platform_warning(:provider_for_resource) - provider = Chef::Platform.provider_for_resource(file, :foo) - expect(provider).to be_an_instance_of(Chef::Provider::File) - expect(provider.new_resource).to equal(file) - expect(provider.run_context).to equal(run_context) - end - - it "returns a provider object given a Chef::Resource object which has a valid run context without an action" do - file, run_context = setup_file_resource - expect_platform_warning(:provider_for_resource) - provider = Chef::Platform.provider_for_resource(file) - expect(provider).to be_an_instance_of(Chef::Provider::File) - expect(provider.new_resource).to equal(file) - expect(provider.run_context).to equal(run_context) - end - - it "raises an error when trying to find the provider for a resource with no run context" do - file = Chef::Resource::File.new("whateva") - expect_platform_warning(:provider_for_resource, recurse: false) - expect { Chef::Platform.provider_for_resource(file) }.to raise_error(ArgumentError) - end - - it "does not support finding a provider by resource and node -- a run context is required" do - expect { Chef::Platform.provider_for_node("node", "resource") }.to raise_error(NotImplementedError) - end - - it "should update the provider map with map" do - expect_platform_warning(:set, times: 7) - Chef::Platform.set( - :platform => :darwin, - :version => "9.2.2", - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:darwin]["9.2.2"][:file]).to eql("masterful") - Chef::Platform.set( - :platform => :darwin, - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:darwin][:default][:file]).to eql("masterful") - Chef::Platform.set( - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:default][:file]).to eql("masterful") - - Chef::Platform.set( - :platform => :hero, - :version => "9.2.2", - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:hero]["9.2.2"][:file]).to eql("masterful") - - Chef::Platform.set( - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:default][:file]).to eql("masterful") - - Chef::Platform.platforms = {} - - Chef::Platform.set( - :resource => :file, - :provider => "masterful" - ) - expect(Chef::Platform.platforms[:default][:file]).to eql("masterful") - - Chef::Platform.platforms = { :neurosis => {} } - Chef::Platform.set(:platform => :neurosis, :resource => :package, :provider => "masterful") - expect(Chef::Platform.platforms[:neurosis][:default][:package]).to eql("masterful") - - end - - it "does not overwrite the platform map when using :default platform" do - expect_platform_warning(:set) - Chef::Platform.set( - :resource => :file, - :platform => :default, - :provider => "new school" - ) - expect(Chef::Platform.platforms[:default][:file]).to eql("new school") - expect(Chef::Platform.platforms[:default][:cat]).to eql("nice") - end - - end - -end diff --git a/spec/unit/property/validation_spec.rb b/spec/unit/property/validation_spec.rb index 4e1b252863..13afcdfbc2 100644 --- a/spec/unit/property/validation_spec.rb +++ b/spec/unit/property/validation_spec.rb @@ -100,13 +100,10 @@ describe "Chef::Resource.property validation" do expect(resource.x).to be_nil end unless tags.include?(:nillable) - it "changing x to nil warns that the get will change to a set in Chef 13 and does not change the value" do + it "changing x to nil does a set" do resource.instance_eval { @x = "default" } - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /An attempt was made to change x from "default" to nil by calling x\(nil\). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x nil).to eq "default" - expect(resource.x).to eq "default" + expect(resource.x nil).to eq nil + expect(resource.x).to eq nil end end end @@ -116,13 +113,10 @@ describe "Chef::Resource.property validation" do expect(resource.x nil).to be_nil expect(resource.x).to be_nil end - it "changing x to nil warns that the get will change to a set in Chef 13 and does not change the value" do + it "changing x to nil does a set" do resource.instance_eval { @x = "default" } - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /An attempt was made to change x from "default" to nil by calling x\(nil\). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x nil).to eq "default" - expect(resource.x).to eq "default" + expect(resource.x nil).to eq nil + expect(resource.x).to eq nil end end elsif tags.include?(:nillable) @@ -134,26 +128,17 @@ describe "Chef::Resource.property validation" do expect(resource.x).to eq nil end end - else + elsif tags.include?(:delayed_nil_default_failure) it "property :x, #{validation}, default: nil warns that the default is invalid" do - expect { resource_class.class_eval("property :x, #{validation}, default: nil", __FILE__, __LINE__) }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Default value nil is invalid for property x of resource chef_resource_property_spec_(\d+). Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property \(for example, 'property :x, \[ String, nil \], default: nil'\)./ + expect { resource_class.class_eval("property :x, #{validation}, default: nil", __FILE__, __LINE__) }.not_to raise_error + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed, /Property x must be one of: .* You passed nil./ end - context "With property :x, #{validation}, default: nil" do - before do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource_class.class_eval("property :x, #{validation}, default: nil", __FILE__, __LINE__) - Chef::Config[:treat_deprecation_warnings_as_errors] = true - end - - it "changing x to nil emits a warning that the value is invalid and does not change the value" do - resource.instance_eval { @x = "default" } - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /nil is an invalid value for x of resource chef_resource_property_spec_(\d+). In Chef 13, this warning will change to an error./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x nil).to eq "default" - expect(resource.x).to eq "default" - end + elsif tags.include?(:skip_nil_default) + # intentionally left blank + else + it "property :x, #{validation}, default: nil warns that the default is invalid" do + expect { resource_class.class_eval("property :x, #{validation}, default: nil", __FILE__, __LINE__) }.to raise_error Chef::Exceptions::ValidationFailed, + /Property x must be one of: .* You passed nil./ end end end @@ -174,12 +159,10 @@ describe "Chef::Resource.property validation" do it "set to invalid value raises ValidationFailed" do expect { resource.x 10 }.to raise_error Chef::Exceptions::ValidationFailed end - it "set to nil emits a deprecation warning and does a get" do - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - Chef::Config[:treat_deprecation_warnings_as_errors] = false + it "set to nil does a set" do resource.x "str" - expect(resource.x nil).to eq "str" - expect(resource.x).to eq "str" + expect(resource.x nil).to eq nil + expect(resource.x).to eq nil end end context "when the variable does not have an initial value" do @@ -206,12 +189,9 @@ describe "Chef::Resource.property validation" do it "get succeeds" do expect(resource.x).to eq "default" end - it "set(nil) emits a warning that the value will be set, but does not set the value" do - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /An attempt was made to change x from "default" to nil by calling x\(nil\). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x nil).to eq "default" - expect(resource.x).to eq "default" + it "set(nil) does a set" do + expect(resource.x nil).to eq nil + expect(resource.x).to eq nil end it "set to valid value succeeds" do expect(resource.x "str").to eq "str" @@ -328,11 +308,17 @@ describe "Chef::Resource.property validation" do # Proc validation_test "is: proc { |x| x }", [ true, 1 ], - [ false ] + [ false ], + # this is somewhat complicated, we test adding `default: nil` and that the default fails, but with a proc the + # validation is delayed until access, so we have to test after access not after declaring the default + :delayed_nil_default_failure validation_test "is: proc { |x| x > blah }", [ 10 ], - [ -1 ] + [ -1 ], + # here the test of adding `default: nil` just causes the proc to explode because nil gets passed to the proc + # which throws a NoMethodError on NilClass for the `>` method. + :skip_nil_default validation_test "is: nil", [ ], @@ -589,15 +575,21 @@ describe "Chef::Resource.property validation" do it "value nil emits a validation failed error because it must have a value" do expect { resource.x nil }.to raise_error Chef::Exceptions::ValidationFailed end - context "and value is set to something other than nil" do - before { resource.x 10 } - it "value nil emits a deprecation warning and does a get" do - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource.x 1 - expect(resource.x nil).to eq 1 - expect(resource.x).to eq 1 - end + end + + with_property ":x, String, required: true" do + it "if x is not specified, retrieval fails" do + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + end + it "value nil is not valid (required means 'not nil')" do + expect { resource.x nil }.to raise_error Chef::Exceptions::ValidationFailed + end + it "value '1' is valid" do + expect(resource.x "1").to eq "1" + expect(resource.x).to eq "1" + end + it "value 1 is invalid" do + expect { resource.x 1 }.to raise_error Chef::Exceptions::ValidationFailed end end @@ -625,12 +617,8 @@ describe "Chef::Resource.property validation" do expect(resource.x 1).to eq 1 expect(resource.x).to eq 1 end - it "value nil emits a deprecation warning and does a get" do - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource.x 1 - expect(resource.x nil).to eq 1 - expect(resource.x).to eq 1 + it "value nil is invalid" do + expect { resource.x nil }.to raise_error Chef::Exceptions::ValidationFailed end end @@ -643,11 +631,7 @@ describe "Chef::Resource.property validation" do expect(resource.x).to eq 1 end it "value nil is invalid" do - expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource.x 1 - expect(resource.x nil).to eq 1 - expect(resource.x).to eq 1 + expect { resource.x nil }.to raise_error Chef::Exceptions::ValidationFailed end end end @@ -675,15 +659,13 @@ describe "Chef::Resource.property validation" do end it "value '1' is invalid" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false expect { resource.x "1" }.to raise_error Chef::Exceptions::ValidationFailed end - it "value nil does a get" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false + it "value nil does a set" do resource.x 1 resource.x nil - expect(resource.x).to eq 1 + expect(resource.x).to eq nil end end end @@ -709,10 +691,10 @@ describe "Chef::Resource.property validation" do expect { resource.x "1" }.to raise_error Chef::Exceptions::ValidationFailed end - it "value nil does a get" do + it "value nil does a set" do resource.x 1 resource.x nil - expect(resource.x).to eq 1 + expect(resource.x).to eq nil end end end diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb index 0e7bf53ec5..bd90891b63 100644 --- a/spec/unit/property_spec.rb +++ b/spec/unit/property_spec.rb @@ -82,12 +82,10 @@ describe "Chef::Resource.property" do expect(resource.bare_property 10).to eq 10 expect(resource.bare_property).to eq 10 end - it "emits a deprecation warning and does a get, if set to nil" do + it "nil does a set" do expect(resource.bare_property 10).to eq 10 - expect { resource.bare_property nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.bare_property nil).to eq 10 - expect(resource.bare_property).to eq 10 + expect(resource.bare_property nil).to eq nil + expect(resource.bare_property).to eq nil end it "can be updated" do expect(resource.bare_property 10).to eq 10 @@ -110,6 +108,16 @@ describe "Chef::Resource.property" do end end + with_property ":Straße" do + it "properties with UTF-8 in their name work" do + expect(resource.Straße).to eql(nil) + expect(resource.Straße "foo").to eql("foo") + expect(resource.Straße).to eql("foo") + expect(resource.Straße = "bar").to eql("bar") + expect(resource.Straße).to eql("bar") + end + end + with_property ":x, name_property: true" do context "and subclass" do let(:subresource_class) do @@ -585,24 +593,8 @@ describe "Chef::Resource.property" do end context "validation of defaults" do - it "When a class is declared with property :x, String, default: 10, a warning is emitted" do - expect { resource_class.class_eval { property :x, String, default: 10 } }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Default value 10 is invalid for property x of resource chef_resource_property_spec_(\d+). In Chef 13 this will become an error: Property x must be one of: String! You passed 10./ - end - context "With property :x, String, default: 10" do - before do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - resource_class.class_eval { property :x, String, default: 10 } - Chef::Config[:treat_deprecation_warnings_as_errors] = true - end - - it "when x is set, no error is raised" do - expect(resource.x "hi").to eq "hi" - expect(resource.x).to eq "hi" - end - it "when x is retrieved, no validation error is raised" do - expect(resource.x).to eq 10 - end + it "When a class is declared with property :x, String, default: 10, it immediately fails validation" do + expect { resource_class.class_eval { property :x, String, default: 10 } }.to raise_error Chef::Exceptions::ValidationFailed end with_property ":x, String, default: lazy { Namer.next_index }" do @@ -613,12 +605,9 @@ describe "Chef::Resource.property" do expect(resource.x "hi").to eq "hi" expect(resource.x).to eq "hi" end - it "when x is retrieved, an invalid default warning is emitted and the value is returned" do - expect { resource.x }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Default value 1 is invalid for property x of resource chef_resource_property_spec_(\d+). In Chef 13 this will become an error: Property x must be one of: String! You passed 1./ + it "when x is retrieved, it fails validation" do + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed expect(Namer.current_index).to eq 1 - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x).to eq 2 end end @@ -731,11 +720,8 @@ describe "Chef::Resource.property" do end end with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do - it "when x is retrieved, it is coerced and emits an invalid default warning, but still returns the value" do - expect { resource.x }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Default value 10 is invalid for property x of resource chef_resource_property_spec_(\d+). In Chef 13 this will become an error: Property x must be one of: Integer! You passed "101"./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x).to eq "102" + it "when x is retrieved, it is coerced and fails validation" do + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed end end with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do @@ -744,11 +730,8 @@ describe "Chef::Resource.property" do end end with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do - it "when x is retrieved, it is coerced and emits an invalid default warning; the value is still returned." do - expect { resource.x }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Default value 10 is invalid for property x of resource chef_resource_property_spec_(\d+). In Chef 13 this will become an error: Property x must be one of: Integer! You passed "101"./ - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect(resource.x).to eq "102" + it "when x is retrieved, it is coerced and fails validation" do + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed end end with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do @@ -1057,7 +1040,7 @@ describe "Chef::Resource.property" do include Chef::Mixin::Properties property_type(is: [:a, :b], default: :c) end - end.to raise_error(Chef::Exceptions::DeprecatedFeatureError, /Default value :c is invalid for property <property type>./) + end.to raise_error(Chef::Exceptions::ValidationFailed) expect do module ::PropertySpecPropertyTypes include Chef::Mixin::Properties @@ -1126,6 +1109,20 @@ describe "Chef::Resource.property" do end + context "redefining Object methods" do + it "disallows redefining Object methods" do + expect { resource_class.class_eval { property :hash } }.to raise_error(ArgumentError) + end + + it "disallows redefining Chef::Resource methods" do + expect { resource_class.class_eval { property :action } }.to raise_error(ArgumentError) + end + + it "allows redefining properties on Chef::Resource" do + expect { resource_class.class_eval { property :sensitive } }.not_to raise_error + end + end + context "with a custom property type" do class CustomPropertyType < Chef::Property end diff --git a/spec/unit/provider/service/solaris_smf_service_spec.rb b/spec/unit/provider/service/solaris_smf_service_spec.rb index c6835bed64..584176b944 100644 --- a/spec/unit/provider/service/solaris_smf_service_spec.rb +++ b/spec/unit/provider/service/solaris_smf_service_spec.rb @@ -198,6 +198,33 @@ describe Chef::Provider::Service::Solaris do end end + describe "when enabling the service recursively" do + before(:each) do + @provider.current_resource = @current_resource + end + + it "should call svcadm enable -s -r chef" do + @new_resource.options("-r") + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status) + expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", @current_resource.service_name).and_return(@success) + @provider.load_current_resource + expect(@provider.enable_service).to be_truthy + expect(@current_resource.enabled).to be_truthy + end + + it "should call svcadm enable -s -r -t chef when passed an array of options" do + @new_resource.options(["-r", "-t"]) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status) + expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", "-t", @current_resource.service_name).and_return(@success) + @provider.load_current_resource + expect(@provider.enable_service).to be_truthy + expect(@current_resource.enabled).to be_truthy + end + + end + describe "when disabling the service" do before(:each) do @provider.current_resource = @current_resource @@ -215,7 +242,16 @@ describe Chef::Provider::Service::Solaris do expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@disabled_svc_status) expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "chef").and_return(@success) @provider.load_current_resource - expect(@provider.stop_service).to be_truthy + expect(@provider.disable_service).to be_truthy + expect(@current_resource.enabled).to be_falsey + end + + it "should call svcadm disable chef with options" do + @new_resource.options("-t") + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@disabled_svc_status) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "-t", "chef").and_return(@success) + @provider.load_current_resource + expect(@provider.disable_service).to be_truthy expect(@current_resource.enabled).to be_falsey end diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb index 5ee33b14dd..cb500da34a 100644 --- a/spec/unit/recipe_spec.rb +++ b/spec/unit/recipe_spec.rb @@ -307,7 +307,7 @@ describe Chef::Recipe do it "gives a sane error message when using method_missing" do expect do recipe.no_such_resource("foo") - end.to raise_error(NoMethodError, %q{No resource or method named `no_such_resource' for `Chef::Recipe "test"'}) + end.to raise_error(NoMethodError, /undefined method `no_such_resource' for cookbook: hjk, recipe: test :Chef::Recipe/) end it "gives a sane error message when using method_missing 'bare'" do @@ -316,7 +316,7 @@ describe Chef::Recipe do # Giving an argument will change this from NameError to NoMethodError no_such_resource end - end.to raise_error(NameError, %q{No resource, method, or local variable named `no_such_resource' for `Chef::Recipe "test"'}) + end.to raise_error(NameError, /undefined local variable or method `no_such_resource' for cookbook: hjk, recipe: test :Chef::Recipe/) end it "gives a sane error message when using build_resource" do diff --git a/spec/unit/resource/cookbook_file_spec.rb b/spec/unit/resource/cookbook_file_spec.rb index 6886ce1f31..05c37446a6 100644 --- a/spec/unit/resource/cookbook_file_spec.rb +++ b/spec/unit/resource/cookbook_file_spec.rb @@ -1,7 +1,7 @@ # # Author:: Daniel DeLeo (<dan@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2010-2016, Chef Software, Inc. +# Copyright:: Copyright 2010-2017, Chef Software Inc. #p License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -64,7 +64,7 @@ describe Chef::Resource::CookbookFile do end it "describes the state" do - state = @cookbook_file.state + state = @cookbook_file.state_for_resource_reporter if Chef::Platform.windows? puts state expect(state[:rights]).to eq([{ :permissions => :read, :principals => "Everyone" }]) diff --git a/spec/unit/resource/cron_spec.rb b/spec/unit/resource/cron_spec.rb index 6e867b75e1..e2bfc321e8 100644 --- a/spec/unit/resource/cron_spec.rb +++ b/spec/unit/resource/cron_spec.rb @@ -170,7 +170,7 @@ describe Chef::Resource::Cron do end it "describes the state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:minute]).to eq("1") expect(state[:hour]).to eq("2") expect(state[:day]).to eq("3") diff --git a/spec/unit/resource/deploy_spec.rb b/spec/unit/resource/deploy_spec.rb index a758638244..e008d79c29 100644 --- a/spec/unit/resource/deploy_spec.rb +++ b/spec/unit/resource/deploy_spec.rb @@ -270,7 +270,7 @@ describe Chef::Resource::Deploy do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:deploy_to]).to eq("/") expect(state[:revision]).to eq("1.2.3") end diff --git a/spec/unit/resource/directory_spec.rb b/spec/unit/resource/directory_spec.rb index cfb3ade135..b3a0134024 100644 --- a/spec/unit/resource/directory_spec.rb +++ b/spec/unit/resource/directory_spec.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -69,7 +69,7 @@ describe Chef::Resource::Directory do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:group]).to eq("wheel") expect(state[:mode]).to eq("0664") expect(state[:owner]).to eq("root") diff --git a/spec/unit/resource/env_spec.rb b/spec/unit/resource/env_spec.rb index cff862b69e..1c63ab519f 100644 --- a/spec/unit/resource/env_spec.rb +++ b/spec/unit/resource/env_spec.rb @@ -73,7 +73,7 @@ describe Chef::Resource::Env do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:value]).to eq("level7") end diff --git a/spec/unit/resource/file_spec.rb b/spec/unit/resource/file_spec.rb index 19304cb6b8..4004798dad 100644 --- a/spec/unit/resource/file_spec.rb +++ b/spec/unit/resource/file_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -101,7 +101,7 @@ describe Chef::Resource::File do context "on unix", :unix_only do it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:owner]).to eq("root") expect(state[:group]).to eq("wheel") expect(state[:mode]).to eq("0644") @@ -121,7 +121,7 @@ describe Chef::Resource::File do @resource.rights :full_control, "DOMAIN\User" end it "describes its state including windows ACL attributes" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:rights]).to eq([ { :permissions => :read, :principals => "Everyone" }, { :permissions => :full_control, :principals => "DOMAIN\User" } ]) end diff --git a/spec/unit/resource/group_spec.rb b/spec/unit/resource/group_spec.rb index 9d9b5c1111..8772f37a2b 100644 --- a/spec/unit/resource/group_spec.rb +++ b/spec/unit/resource/group_spec.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen (<aj@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>); -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -151,7 +151,7 @@ describe Chef::Resource::Group, "append" do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:members]).to eql(%w{blastoise pikachu}) end diff --git a/spec/unit/resource/ifconfig_spec.rb b/spec/unit/resource/ifconfig_spec.rb index eceba0c319..699ebf1233 100644 --- a/spec/unit/resource/ifconfig_spec.rb +++ b/spec/unit/resource/ifconfig_spec.rb @@ -37,7 +37,7 @@ describe Chef::Resource::Ifconfig do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:inet_addr]).to eq("434.2343.23") expect(state[:mask]).to eq("255.255.545") end diff --git a/spec/unit/resource/link_spec.rb b/spec/unit/resource/link_spec.rb index bd0976d8ea..adfd0020f5 100644 --- a/spec/unit/resource/link_spec.rb +++ b/spec/unit/resource/link_spec.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -121,7 +121,7 @@ describe Chef::Resource::Link do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:to]).to eq("/to/dir/file.tar") expect(state[:owner]).to eq("root") expect(state[:group]).to eq("0664") diff --git a/spec/unit/resource/mdadm_spec.rb b/spec/unit/resource/mdadm_spec.rb index fe9acf807b..f3cadbe499 100644 --- a/spec/unit/resource/mdadm_spec.rb +++ b/spec/unit/resource/mdadm_spec.rb @@ -93,7 +93,7 @@ describe Chef::Resource::Mdadm do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:devices]).to eql(%w{device1 device2}) expect(state[:level]).to eq(1) expect(state[:chunk]).to eq(42) diff --git a/spec/unit/resource/mount_spec.rb b/spec/unit/resource/mount_spec.rb index 832f7644ac..466b6ac8c0 100644 --- a/spec/unit/resource/mount_spec.rb +++ b/spec/unit/resource/mount_spec.rb @@ -1,7 +1,7 @@ # # Author:: Joshua Timberman (<joshua@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -181,7 +181,7 @@ describe Chef::Resource::Mount do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:mount_point]).to eq("123.456") expect(state[:device_type]).to eql(:device) expect(state[:fstype]).to eq("ranked") @@ -202,7 +202,7 @@ describe Chef::Resource::Mount do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:mount_point]).to eq("T:") expect(state[:username]).to eq("Administrator") expect(state[:password]).to eq("Jetstream123!") diff --git a/spec/unit/resource/ohai_spec.rb b/spec/unit/resource/ohai_spec.rb index cf1748002b..574c09eeba 100644 --- a/spec/unit/resource/ohai_spec.rb +++ b/spec/unit/resource/ohai_spec.rb @@ -49,7 +49,7 @@ describe Chef::Resource::Ohai do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:plugin]).to eq("passwd") end diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb index 7ec3c198e4..8c00ea2bdd 100644 --- a/spec/unit/resource/package_spec.rb +++ b/spec/unit/resource/package_spec.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -72,7 +72,7 @@ describe Chef::Resource::Package do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:version]).to eq("10.9.8") expect(state[:options]).to eq("-al") end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index d378da3ed0..067f2da36a 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist (<lamont@chef.io>) -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -210,6 +210,6 @@ describe Chef::Resource::RegistryKey, "state" do it "should return scrubbed values" do @resource.values([ { :name => "poosh", :type => :binary, :data => 255.chr * 1 } ]) - expect(@resource.state).to eql( { :values => [{ :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" }] } ) + expect(@resource.state_for_resource_reporter).to eql( { :values => [{ :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" }] } ) end end diff --git a/spec/unit/resource/remote_directory_spec.rb b/spec/unit/resource/remote_directory_spec.rb index cdca214db6..370b8d8225 100644 --- a/spec/unit/resource/remote_directory_spec.rb +++ b/spec/unit/resource/remote_directory_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,7 +84,7 @@ describe Chef::Resource::RemoteDirectory do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:files_owner]).to eq("root") expect(state[:files_group]).to eq("supergroup") expect(state[:files_mode]).to eq("0664") diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb index 274f98e7f4..eca3db3420 100644 --- a/spec/unit/resource/remote_file_spec.rb +++ b/spec/unit/resource/remote_file_spec.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -183,7 +183,7 @@ describe Chef::Resource::RemoteFile do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter if Chef::Platform.windows? puts state expect(state[:rights]).to eq([{ :permissions => :read, :principals => "Everyone" }]) diff --git a/spec/unit/resource/route_spec.rb b/spec/unit/resource/route_spec.rb index 259ccf7eab..884b477365 100644 --- a/spec/unit/resource/route_spec.rb +++ b/spec/unit/resource/route_spec.rb @@ -95,7 +95,7 @@ describe Chef::Resource::Route do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:netmask]).to eq("lemask") expect(state[:gateway]).to eq("111.111.111") end diff --git a/spec/unit/resource/scm_spec.rb b/spec/unit/resource/scm_spec.rb index f39334348e..679b3bc1fc 100644 --- a/spec/unit/resource/scm_spec.rb +++ b/spec/unit/resource/scm_spec.rb @@ -1,7 +1,7 @@ # # Author:: Daniel DeLeo (<dan@kallistec.com>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -174,7 +174,7 @@ describe Chef::Resource::Scm do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:revision]).to eq("1.2.3") end diff --git a/spec/unit/resource/service_spec.rb b/spec/unit/resource/service_spec.rb index 8d661e2a7a..67a4635983 100644 --- a/spec/unit/resource/service_spec.rb +++ b/spec/unit/resource/service_spec.rb @@ -124,6 +124,27 @@ describe Chef::Resource::Service do end.to raise_error(ArgumentError) end + it "should accept an array for options" do + @resource.options ["-r", "-s"] + expect(@resource.options).to eql(["-r", "-s"]) + end + + it "should accept a string for options" do + @resource.options "-r" + expect(@resource.options).to eql(["-r"]) + end + + it "should accept a string with multiple flags for options" do + @resource.options "-r -s" + expect(@resource.options).to eql(["-r", "-s"]) + end + + it "should not accept a boolean for options" do + expect do + @resource.options true + end.to raise_error(ArgumentError) + end + %w{enabled running}.each do |attrib| it "should accept true for #{attrib}" do @resource.send(attrib, true) @@ -166,7 +187,7 @@ describe Chef::Resource::Service do end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:enabled]).to eql(true) expect(state[:running]).to eql(false) end @@ -175,5 +196,4 @@ describe Chef::Resource::Service do expect(@resource.identity).to eq("superfriend") end end - end diff --git a/spec/unit/resource/systemd_unit_spec.rb b/spec/unit/resource/systemd_unit_spec.rb index 7e46872525..ab1004fab0 100644 --- a/spec/unit/resource/systemd_unit_spec.rb +++ b/spec/unit/resource/systemd_unit_spec.rb @@ -109,7 +109,7 @@ describe Chef::Resource::SystemdUnit do @resource.masked false @resource.static false @resource.content "test" - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:active]).to eq(true) expect(state[:enabled]).to eq(true) expect(state[:masked]).to eq(false) diff --git a/spec/unit/resource/template_spec.rb b/spec/unit/resource/template_spec.rb index 9060f02d29..966a86ba6b 100644 --- a/spec/unit/resource/template_spec.rb +++ b/spec/unit/resource/template_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -88,7 +88,7 @@ describe Chef::Resource::Template do context "on unix", :unix_only do it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:owner]).to eq("root") expect(state[:group]).to eq("wheel") expect(state[:mode]).to eq("0644") diff --git a/spec/unit/resource/user_spec.rb b/spec/unit/resource/user_spec.rb index afd3969164..1a3f0284e3 100644 --- a/spec/unit/resource/user_spec.rb +++ b/spec/unit/resource/user_spec.rb @@ -119,7 +119,7 @@ end end it "describes its state" do - state = @resource.state + state = @resource.state_for_resource_reporter expect(state[:uid]).to eq(123) expect(state[:gid]).to eq(456) expect(state[:home]).to eq("/usr/local/root/") diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb index 84cfb52418..4fcfb01233 100644 --- a/spec/unit/resource_reporter_spec.rb +++ b/spec/unit/resource_reporter_spec.rb @@ -3,7 +3,7 @@ # Author:: Prajakta Purohit (<prajakta@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) # -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -399,11 +399,11 @@ describe Chef::ResourceReporter do end it "includes an updated resource's initial state" do - expect(@first_update_report["before"]).to eq(current_resource.state) + expect(@first_update_report["before"]).to eq(current_resource.state_for_resource_reporter) end it "includes an updated resource's final state" do - expect(@first_update_report["after"]).to eq(new_resource.state) + expect(@first_update_report["after"]).to eq(new_resource.state_for_resource_reporter) end it "includes the resource's name" do @@ -540,11 +540,11 @@ describe Chef::ResourceReporter do end it "includes an updated resource's initial state" do - expect(@first_update_report["before"]).to eq(@current_resource.state) + expect(@first_update_report["before"]).to eq(@current_resource.state_for_resource_reporter) end it "includes an updated resource's final state" do - expect(@first_update_report["after"]).to eq(@new_resource.state) + expect(@first_update_report["after"]).to eq(@new_resource.state_for_resource_reporter) end it "includes the resource's name" do diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index c1aeb256fa..a83b22ea0f 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -160,7 +160,7 @@ describe Chef::Resource do end it "describes its state" do - resource_state = file_resource.state + resource_state = file_resource.state_for_resource_reporter expect(resource_state.keys).to match_array([:checksum, :owner, :group, :mode]) expect(resource_state[:checksum]).to eq("abc123") expect(resource_state[:owner]).to eq("root") @@ -798,11 +798,7 @@ describe Chef::Resource do snitch_var1 = snitch_var2 = 0 runner = Chef::Runner.new(run_context) - Chef::Config[:treat_deprecation_warnings_as_errors] = false - Chef::Platform.set( - :resource => :cat, - :provider => Chef::Provider::SnakeOil - ) + Chef::Provider::SnakeOil.provides :cat resource1.only_if { snitch_var1 = 1 } resource1.not_if { snitch_var2 = 2 } diff --git a/spec/unit/rest/auth_credentials_spec.rb b/spec/unit/rest/auth_credentials_spec.rb deleted file mode 100644 index 2728463c81..0000000000 --- a/spec/unit/rest/auth_credentials_spec.rb +++ /dev/null @@ -1,292 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Christopher Brown (<cb@chef.io>) -# Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. -# Copyright:: Copyright 2010-2016, 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 "spec_helper" -require "uri" -require "net/https" - -describe Chef::REST::AuthCredentials do - before do - @key_file_fixture = CHEF_SPEC_DATA + "/ssl/private_key.pem" - @key = OpenSSL::PKey::RSA.new(IO.read(@key_file_fixture).strip) - @auth_credentials = Chef::REST::AuthCredentials.new("client-name", @key) - end - - it "has a client name" do - expect(@auth_credentials.client_name).to eq("client-name") - end - - it "loads the private key when initialized with the path to the key" do - expect(@auth_credentials.key).to respond_to(:private_encrypt) - expect(@auth_credentials.key).to eq(@key) - end - - describe "when loading the private key" do - it "strips extra whitespace before checking the key" do - key_file_fixture = CHEF_SPEC_DATA + "/ssl/private_key_with_whitespace.pem" - expect { Chef::REST::AuthCredentials.new("client-name", @key_file_fixture) }.not_to raise_error - end - end - - describe "generating signature headers for a request" do - before do - @request_time = Time.at(1270920860) - @request_params = { :http_method => :POST, :path => "/clients", :body => '{"some":"json"}', :host => "localhost" } - allow(Chef::Config).to( - receive(:[]).with(:authentication_protocol_version).and_return(protocol_version)) - end - - context "when configured for version 1.0 of the authn protocol" do - let(:protocol_version) { "1.0" } - - it "generates signature headers for the request" do - allow(Time).to receive(:now).and_return(@request_time) - actual = @auth_credentials.signature_headers(@request_params) - expect(actual["HOST"]).to eq("localhost") - expect(actual["X-OPS-AUTHORIZATION-1"]).to eq("kBssX1ENEwKtNYFrHElN9vYGWS7OeowepN9EsYc9csWfh8oUovryPKDxytQ/") - expect(actual["X-OPS-AUTHORIZATION-2"]).to eq("Wc2/nSSyxdWJjjfHzrE+YrqNQTaArOA7JkAf5p75eTUonCWcvNPjFrZVgKGS") - expect(actual["X-OPS-AUTHORIZATION-3"]).to eq("yhzHJQh+lcVA9wwARg5Hu9q+ddS8xBOdm3Vp5atl5NGHiP0loiigMYvAvzPO") - expect(actual["X-OPS-AUTHORIZATION-4"]).to eq("r9853eIxwYMhn5hLGhAGFQznJbE8+7F/lLU5Zmk2t2MlPY8q3o1Q61YD8QiJ") - expect(actual["X-OPS-AUTHORIZATION-5"]).to eq("M8lIt53ckMyUmSU0DDURoiXLVkE9mag/6Yq2tPNzWq2AdFvBqku9h2w+DY5k") - expect(actual["X-OPS-AUTHORIZATION-6"]).to eq("qA5Rnzw5rPpp3nrWA9jKkPw4Wq3+4ufO2Xs6w7GCjA==") - expect(actual["X-OPS-CONTENT-HASH"]).to eq("1tuzs5XKztM1ANrkGNPah6rW9GY=") - expect(actual["X-OPS-SIGN"]).to match(%r{(version=1\.0)|(algorithm=sha1;version=1.0;)}) - expect(actual["X-OPS-TIMESTAMP"]).to eq("2010-04-10T17:34:20Z") - expect(actual["X-OPS-USERID"]).to eq("client-name") - end - end - - context "when configured for version 1.1 of the authn protocol" do - let(:protocol_version) { "1.1" } - - it "generates the correct signature for version 1.1" do - allow(Time).to receive(:now).and_return(@request_time) - actual = @auth_credentials.signature_headers(@request_params) - expect(actual["HOST"]).to eq("localhost") - expect(actual["X-OPS-CONTENT-HASH"]).to eq("1tuzs5XKztM1ANrkGNPah6rW9GY=") - expect(actual["X-OPS-SIGN"]).to eq("algorithm=sha1;version=1.1;") - expect(actual["X-OPS-TIMESTAMP"]).to eq("2010-04-10T17:34:20Z") - expect(actual["X-OPS-USERID"]).to eq("client-name") - - # mixlib-authN will test the actual signature stuff for each version of - # the protocol so we won't test it again here. - end - end - end -end - -describe Chef::REST::RESTRequest do - let(:url) { URI.parse("http://chef.example.com:4000/?q=chef_is_awesome") } - - def new_request(method = nil) - method ||= :POST - Chef::REST::RESTRequest.new(method, url, @req_body, @headers) - end - - before do - @auth_credentials = Chef::REST::AuthCredentials.new("client-name", CHEF_SPEC_DATA + "/ssl/private_key.pem") - @req_body = '{"json_data":"as_a_string"}' - @headers = { "Content-type" => "application/json", - "Accept" => "application/json", - "Accept-Encoding" => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE, - "Host" => "chef.example.com:4000" } - @request = Chef::REST::RESTRequest.new(:POST, url, @req_body, @headers) - end - - it "stores the url it was created with" do - expect(@request.url).to eq(url) - end - - it "stores the HTTP method" do - expect(@request.method).to eq(:POST) - end - - it "adds the chef version header" do - expect(@request.headers).to eq(@headers.merge("X-Chef-Version" => ::Chef::VERSION)) - end - - describe "configuring the HTTP request" do - let(:url) do - URI.parse("http://homie:theclown@chef.example.com:4000/?q=chef_is_awesome") - end - - it "configures GET requests" do - @req_body = nil - rest_req = new_request(:GET) - expect(rest_req.http_request).to be_a_kind_of(Net::HTTP::Get) - expect(rest_req.http_request.path).to eq("/?q=chef_is_awesome") - expect(rest_req.http_request.body).to be_nil - end - - it "configures POST requests, including the body" do - expect(@request.http_request).to be_a_kind_of(Net::HTTP::Post) - expect(@request.http_request.path).to eq("/?q=chef_is_awesome") - expect(@request.http_request.body).to eq(@req_body) - end - - it "configures PUT requests, including the body" do - rest_req = new_request(:PUT) - expect(rest_req.http_request).to be_a_kind_of(Net::HTTP::Put) - expect(rest_req.http_request.path).to eq("/?q=chef_is_awesome") - expect(rest_req.http_request.body).to eq(@req_body) - end - - it "configures DELETE requests" do - rest_req = new_request(:DELETE) - expect(rest_req.http_request).to be_a_kind_of(Net::HTTP::Delete) - expect(rest_req.http_request.path).to eq("/?q=chef_is_awesome") - expect(rest_req.http_request.body).to be_nil - end - - it "configures HTTP basic auth" do - rest_req = new_request(:GET) - expect(rest_req.http_request.to_hash["authorization"]).to eq(["Basic aG9taWU6dGhlY2xvd24="]) - end - end - - describe "configuring the HTTP client" do - it "configures the HTTP client for the host and port" do - http_client = new_request.http_client - expect(http_client.address).to eq("chef.example.com") - expect(http_client.port).to eq(4000) - end - - it "configures the HTTP client with the read timeout set in the config file" do - Chef::Config[:rest_timeout] = 9001 - expect(new_request.http_client.read_timeout).to eq(9001) - end - - describe "for proxy" do - before do - stub_const("ENV", "http_proxy" => "http://proxy.example.com:3128", - "https_proxy" => "http://sproxy.example.com:3129", - "http_proxy_user" => nil, - "http_proxy_pass" => nil, - "https_proxy_user" => nil, - "https_proxy_pass" => nil, - "no_proxy" => nil - ) - end - - describe "with :no_proxy nil" do - it "configures the proxy address and port when using http scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(true) - expect(http_client.proxy_address).to eq("proxy.example.com") - expect(http_client.proxy_port).to eq(3128) - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - - context "when the url has an https scheme" do - let(:url) { URI.parse("https://chef.example.com:4000/?q=chef_is_awesome") } - - it "configures the proxy address and port when using https scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(true) - expect(http_client.proxy_address).to eq("sproxy.example.com") - expect(http_client.proxy_port).to eq(3129) - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - end - end - - describe "with :no_proxy set" do - before do - stub_const("ENV", "no_proxy" => "10.*,*.example.com") - end - - it "does not configure the proxy address and port when using http scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(false) - expect(http_client.proxy_address).to be_nil - expect(http_client.proxy_port).to be_nil - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - - context "when the url has an https scheme" do - let(:url) { URI.parse("https://chef.example.com:4000/?q=chef_is_awesome") } - - it "does not configure the proxy address and port when using https scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(false) - expect(http_client.proxy_address).to be_nil - expect(http_client.proxy_port).to be_nil - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - end - end - - describe "with :http_proxy_user and :http_proxy_pass set" do - before do - stub_const("ENV", "http_proxy" => "http://homie:theclown@proxy.example.com:3128") - end - - it "configures the proxy user and pass when using http scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(true) - expect(http_client.proxy_user).to eq("homie") - expect(http_client.proxy_pass).to eq("theclown") - end - - context "when the url has an https scheme" do - let(:url) { URI.parse("https://chef.example.com:4000/?q=chef_is_awesome") } - - it "does not configure the proxy user and pass when using https scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(false) - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - end - end - - describe "with :https_proxy_user and :https_proxy_pass set" do - before do - stub_const("ENV", "http_proxy" => "http://proxy.example.com:3128", - "https_proxy" => "https://homie:theclown@sproxy.example.com:3129" - ) - end - - it "does not configure the proxy user and pass when using http scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(true) - expect(http_client.proxy_user).to be_nil - expect(http_client.proxy_pass).to be_nil - end - - context "when the url has an https scheme" do - let(:url) { URI.parse("https://chef.example.com:4000/?q=chef_is_awesome") } - - it "configures the proxy user and pass when using https scheme" do - http_client = new_request.http_client - expect(http_client.proxy?).to eq(true) - expect(http_client.proxy_user).to eq("homie") - expect(http_client.proxy_pass).to eq("theclown") - end - end - end - end - end -end diff --git a/spec/unit/rest_spec.rb b/spec/unit/rest_spec.rb deleted file mode 100644 index ea3bd88023..0000000000 --- a/spec/unit/rest_spec.rb +++ /dev/null @@ -1,753 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Christopher Brown (<cb@chef.io>) -# Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. -# Copyright:: Copyright 2010-2016, 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 "spec_helper" -require "uri" -require "net/https" -require "stringio" - -SIGNING_KEY_DOT_PEM = "-----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA49TA0y81ps0zxkOpmf5V4/c4IeR5yVyQFpX3JpxO4TquwnRh -8VSUhrw8kkTLmB3cS39Db+3HadvhoqCEbqPE6915kXSuk/cWIcNozujLK7tkuPEy -YVsyTioQAddSdfe+8EhQVf3oHxaKmUd6waXrWqYCnhxgOjxocenREYNhZ/OETIei -PbOku47vB4nJK/0GhKBytL2XnsRgfKgDxf42BqAi1jglIdeq8lAWZNF9TbNBU21A -O1iuT7Pm6LyQujhggPznR5FJhXKRUARXBJZawxpGV4dGtdcahwXNE4601aXPra+x -PcRd2puCNoEDBzgVuTSsLYeKBDMSfs173W1QYwIDAQABAoIBAGF05q7vqOGbMaSD -2Q7YbuE/JTHKTBZIlBI1QC2x+0P5GDxyEFttNMOVzcs7xmNhkpRw8eX1LrInrpMk -WsIBKAFFEfWYlf0RWtRChJjNl+szE9jQxB5FJnWtJH/FHa78tR6PsF24aQyzVcJP -g0FGujBihwgfV0JSCNOBkz8MliQihjQA2i8PGGmo4R4RVzGfxYKTIq9vvRq/+QEa -Q4lpVLoBqnENpnY/9PTl6JMMjW2b0spbLjOPVwDaIzXJ0dChjNXo15K5SHI5mALJ -I5gN7ODGb8PKUf4619ez194FXq+eob5YJdilTFKensIUvt3YhP1ilGMM+Chi5Vi/ -/RCTw3ECgYEA9jTw4wv9pCswZ9wbzTaBj9yZS3YXspGg26y6Ohq3ZmvHz4jlT6uR -xK+DDcUiK4072gci8S4Np0fIVS7q6ivqcOdzXPrTF5/j+MufS32UrBbUTPiM1yoO -ECcy+1szl/KoLEV09bghPbvC58PFSXV71evkaTETYnA/F6RK12lEepcCgYEA7OSy -bsMrGDVU/MKJtwqyGP9ubA53BorM4Pp9VVVSCrGGVhb9G/XNsjO5wJC8J30QAo4A -s59ZzCpyNRy046AB8jwRQuSwEQbejSdeNgQGXhZ7aIVUtuDeFFdaIz/zjVgxsfj4 -DPOuzieMmJ2MLR4F71ocboxNoDI7xruPSE8dDhUCgYA3vx732cQxgtHwAkeNPJUz -dLiE/JU7CnxIoSB9fYUfPLI+THnXgzp7NV5QJN2qzMzLfigsQcg3oyo6F2h7Yzwv -GkjlualIRRzCPaCw4Btkp7qkPvbs1QngIHALt8fD1N69P3DPHkTwjG4COjKWgnJq -qoHKS6Fe/ZlbigikI6KsuwKBgQCTlSLoyGRHr6oj0hqz01EDK9ciMJzMkZp0Kvn8 -OKxlBxYW+jlzut4MQBdgNYtS2qInxUoAnaz2+hauqhSzntK3k955GznpUatCqx0R -b857vWviwPX2/P6+E3GPdl8IVsKXCvGWOBZWTuNTjQtwbDzsUepWoMgXnlQJSn5I -YSlLxQKBgQD16Gw9kajpKlzsPa6XoQeGmZALT6aKWJQlrKtUQIrsIWM0Z6eFtX12 -2jjHZ0awuCQ4ldqwl8IfRogWMBkHOXjTPVK0YKWWlxMpD/5+bGPARa5fir8O1Zpo -Y6S6MeZ69Rp89ma4ttMZ+kwi1+XyHqC/dlcVRW42Zl5Dc7BALRlJjQ== ------END RSA PRIVATE KEY-----" - -describe Chef::REST do - let(:base_url) { "http://chef.example.com:4000" } - - let(:monkey_uri) { URI.parse("http://chef.example.com:4000/monkey") } - - let(:log_stringio) { StringIO.new } - - let(:request_id) { "1234" } - - let(:rest) do - allow(Chef::REST::CookieJar).to receive(:instance).and_return({}) - allow(Chef::RequestID.instance).to receive(:request_id).and_return(request_id) - rest = Chef::REST.new(base_url, nil, nil) - Chef::REST::CookieJar.instance.clear - rest - end - - let(:standard_read_headers) { { "Accept" => "application/json", "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID" => request_id, "X-Ops-Server-API-Version" => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION } } - let(:standard_write_headers) { { "Accept" => "application/json", "Content-Type" => "application/json", "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID" => request_id, "X-Ops-Server-API-Version" => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION } } - - before(:each) do - Chef::Log.init(log_stringio) - Chef::Config[:treat_deprecation_warnings_as_errors] = false - end - - it "should have content length validation middleware after compressor middleware" do - middlewares = rest.instance_variable_get(:@middlewares) - content_length = middlewares.find_index { |e| e.is_a? Chef::HTTP::ValidateContentLength } - decompressor = middlewares.find_index { |e| e.is_a? Chef::HTTP::Decompressor } - - expect(content_length).not_to be_nil - expect(decompressor).not_to be_nil - expect(decompressor < content_length).to be_truthy - end - - it "should allow the options hash to be frozen" do - options = {}.freeze - # should not raise any exception - Chef::REST.new(base_url, nil, nil, options) - end - - it "emits a deprecation warning" do - Chef::Config[:treat_deprecation_warnings_as_errors] = true - expect { Chef::REST.new(base_url) }.to raise_error Chef::Exceptions::DeprecatedFeatureError, - /Chef::REST is deprecated. Please use Chef::ServerAPI, or investigate Ridley or ChefAPI./ - end - - context "when created with a chef zero URL" do - - let(:url) { "chefzero://localhost:1" } - - it "does not load the signing key" do - expect { Chef::REST.new(url) }.to_not raise_error - end - end - - describe "calling an HTTP verb on a path or absolute URL" do - it "adds a relative URL to the base url it was initialized with" do - expect(rest.create_url("foo/bar/baz")).to eq(URI.parse(base_url + "/foo/bar/baz")) - end - - it "replaces the base URL when given an absolute URL" do - expect(rest.create_url("http://chef-rulez.example.com:9000")).to eq(URI.parse("http://chef-rulez.example.com:9000")) - end - - it "makes a :GET request with the composed url object" do - expect(rest).to receive(:send_http_request). - with(:GET, monkey_uri, standard_read_headers, false). - and_return([1, 2, 3]) - expect(rest).to receive(:apply_response_middleware).with(1, 2, 3).and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.get_rest("monkey") - end - - it "makes a :GET reqest for a streaming download with the composed url" do - expect(rest).to receive(:streaming_request).with("monkey", {}) - rest.get_rest("monkey", true) - end - - it "makes a :DELETE request with the composed url object" do - expect(rest).to receive(:send_http_request). - with(:DELETE, monkey_uri, standard_read_headers, false). - and_return([1, 2, 3]) - expect(rest).to receive(:apply_response_middleware).with(1, 2, 3).and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.delete_rest("monkey") - end - - it "makes a :POST request with the composed url object and data" do - expect(rest).to receive(:send_http_request). - with(:POST, monkey_uri, standard_write_headers, "\"data\""). - and_return([1, 2, 3]) - expect(rest).to receive(:apply_response_middleware).with(1, 2, 3).and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.post_rest("monkey", "data") - end - - it "makes a :PUT request with the composed url object and data" do - expect(rest).to receive(:send_http_request). - with(:PUT, monkey_uri, standard_write_headers, "\"data\""). - and_return([1, 2, 3]) - expect(rest).to receive(:apply_response_middleware).with(1, 2, 3).and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.put_rest("monkey", "data") - end - end - - describe "legacy API" do - let(:rest) do - Chef::REST.new(base_url) - end - - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" - end - - it "responds to raw_http_request as a public method" do - expect(rest.public_methods.map(&:to_s)).to include("raw_http_request") - end - - it "calls the authn middleware" do - data = "\"secure data\"" - - auth_headers = standard_write_headers.merge({ "auth_done" => "yep" }) - - expect(rest.authenticator).to receive(:handle_request). - with(:POST, monkey_uri, standard_write_headers, data). - and_return([:POST, monkey_uri, auth_headers, data]) - expect(rest).to receive(:send_http_request). - with(:POST, monkey_uri, auth_headers, data). - and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.raw_http_request(:POST, monkey_uri, standard_write_headers, data) - end - - it "sets correct authn headers" do - data = "\"secure data\"" - method, uri, auth_headers, d = rest.authenticator.handle_request(:POST, monkey_uri, standard_write_headers, data) - - expect(rest).to receive(:send_http_request). - with(:POST, monkey_uri, auth_headers, data). - and_return([1, 2, 3]) - expect(rest).to receive("success_response?".to_sym).with(1).and_return(true) - rest.raw_http_request(:POST, monkey_uri, standard_write_headers, data) - end - end - - describe "when configured to authenticate to the Chef server" do - let(:base_url) { URI.parse("http://chef.example.com:4000") } - - let(:rest) do - Chef::REST.new(base_url) - end - - before do - Chef::Config[:node_name] = "webmonkey.example.com" - Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" - end - - it "configures itself to use the node_name and client_key in the config by default" do - expect(rest.client_name).to eq("webmonkey.example.com") - expect(rest.signing_key_filename).to eq(CHEF_SPEC_DATA + "/ssl/private_key.pem") - end - - it "provides access to the raw key data" do - expect(rest.signing_key).to eq(SIGNING_KEY_DOT_PEM) - end - - it "does not error out when initialized without credentials" do - rest = Chef::REST.new(base_url, nil, nil) #should_not raise_error hides the bt from you, so screw it. - expect(rest.client_name).to be_nil - expect(rest.signing_key).to be_nil - end - - it "indicates that requests should not be signed when it has no credentials" do - rest = Chef::REST.new(base_url, nil, nil) - expect(rest.sign_requests?).to be_falsey - end - - it "raises PrivateKeyMissing when the key file doesn't exist" do - expect { Chef::REST.new(base_url, "client-name", "/dev/null/nothing_here") }.to raise_error(Chef::Exceptions::PrivateKeyMissing) - end - - it "raises InvalidPrivateKey when the key file doesnt' look like a key" do - invalid_key_file = CHEF_SPEC_DATA + "/bad-config.rb" - expect { Chef::REST.new(base_url, "client-name", invalid_key_file) }.to raise_error(Chef::Exceptions::InvalidPrivateKey) - end - - it "can take private key as a sting :raw_key in options during initializaton" do - expect(Chef::REST.new(base_url, "client-name", nil, :raw_key => SIGNING_KEY_DOT_PEM).signing_key).to eq(SIGNING_KEY_DOT_PEM) - end - - it "raises InvalidPrivateKey when the key passed as string :raw_key in options doesnt' look like a key" do - expect { Chef::REST.new(base_url, "client-name", nil, :raw_key => "bad key string") }.to raise_error(Chef::Exceptions::InvalidPrivateKey) - end - - end - - context "when making REST requests" do - let(:body) { "ninja" } - - let(:http_response) do - http_response = Net::HTTPSuccess.new("1.1", "200", "successful rest req") - allow(http_response).to receive(:read_body) - allow(http_response).to receive(:body).and_return(body) - http_response["Content-Length"] = body.bytesize.to_s - http_response - end - - let(:host_header) { "one" } - - let(:url) { URI.parse("http://one:80/?foo=bar") } - - let(:base_url) { "http://chef.example.com:4000" } - - let!(:http_client) do - http_client = Net::HTTP.new(url.host, url.port) - allow(http_client).to receive(:request).and_yield(http_response).and_return(http_response) - http_client - end - - let(:rest) do - allow(Net::HTTP).to receive(:new).and_return(http_client) - allow(Chef::REST::CookieJar).to receive(:instance).and_return({}) - allow(Chef::RequestID.instance).to receive(:request_id).and_return(request_id) - rest = Chef::REST.new(base_url, nil, nil) - Chef::REST::CookieJar.instance.clear - rest - end - - before(:each) do - Chef::Config[:ssl_client_cert] = nil - Chef::Config[:ssl_client_key] = nil - end - - describe "as JSON API requests" do - let(:request_mock) { {} } - - let(:base_headers) do #FIXME: huh? - { - "Accept" => "application/json", - "X-Chef-Version" => Chef::VERSION, - "Accept-Encoding" => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE, - "Host" => host_header, - "X-REMOTE-REQUEST-ID" => request_id, - "X-Ops-Server-API-Version" => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION, - } - end - - before do - allow(Net::HTTP::Get).to receive(:new).and_return(request_mock) - end - - it "should always include the X-Chef-Version header" do - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", base_headers).and_return(request_mock) - rest.request(:GET, url, {}) - end - - it "should always include the X-Remote-Request-Id header" do - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", base_headers).and_return(request_mock) - rest.request(:GET, url, {}) - end - - it "sets the user agent to chef-client" do - # XXX: must reset to default b/c knife changes the UA - Chef::REST::RESTRequest.user_agent = Chef::REST::RESTRequest::DEFAULT_UA - rest.request(:GET, url, {}) - expect(request_mock["User-Agent"]).to match(/^Chef Client\/#{Chef::VERSION}/) - end - - # CHEF-3140 - context "when configured to disable compression" do - let(:rest) do - allow(Net::HTTP).to receive(:new).and_return(http_client) - Chef::REST.new(base_url, nil, nil, :disable_gzip => true) - end - - it "does not accept encoding gzip" do - expect(rest.send(:build_headers, :GET, url, {})).not_to have_key("Accept-Encoding") - end - - it "does not decompress a response encoded as gzip" do - http_response.add_field("content-encoding", "gzip") - request = Net::HTTP::Get.new(url.path) - expect(Net::HTTP::Get).to receive(:new).and_return(request) - # will raise a Zlib error if incorrect - expect(rest.request(:GET, url, {})).to eq("ninja") - end - end - - context "when configured with custom http headers" do - let(:custom_headers) do - { - "X-Custom-ChefSecret" => "sharpknives", - "X-Custom-RequestPriority" => "extremely low", - } - end - - before(:each) do - Chef::Config[:custom_http_headers] = custom_headers - end - - after(:each) do - Chef::Config[:custom_http_headers] = nil - end - - it "should set them on the http request" do - url_string = an_instance_of(String) - header_hash = hash_including(custom_headers) - expect(Net::HTTP::Get).to receive(:new).with(url_string, header_hash) - rest.request(:GET, url, {}) - end - end - - context "when setting cookies" do - let(:rest) do - allow(Net::HTTP).to receive(:new).and_return(http_client) - Chef::REST::CookieJar.instance["#{url.host}:#{url.port}"] = "cookie monster" - allow(Chef::RequestID.instance).to receive(:request_id).and_return(request_id) - rest = Chef::REST.new(base_url, nil, nil) - rest - end - - it "should set the cookie for this request if one exists for the given host:port" do - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", base_headers.merge("Cookie" => "cookie monster")).and_return(request_mock) - rest.request(:GET, url, {}) - end - end - - it "should build a new HTTP GET request" do - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", base_headers).and_return(request_mock) - rest.request(:GET, url, {}) - end - - it "should build a new HTTP POST request" do - request = Net::HTTP::Post.new(url.path) - expected_headers = base_headers.merge("Content-Type" => "application/json", "Content-Length" => "13") - - expect(Net::HTTP::Post).to receive(:new).with("/?foo=bar", expected_headers).and_return(request) - rest.request(:POST, url, {}, { :one => :two }) - expect(request.body).to eq('{"one":"two"}') - end - - it "should build a new HTTP PUT request" do - request = Net::HTTP::Put.new(url.path) - expected_headers = base_headers.merge("Content-Type" => "application/json", "Content-Length" => "13") - expect(Net::HTTP::Put).to receive(:new).with("/?foo=bar", expected_headers).and_return(request) - rest.request(:PUT, url, {}, { :one => :two }) - expect(request.body).to eq('{"one":"two"}') - end - - it "should build a new HTTP DELETE request" do - expect(Net::HTTP::Delete).to receive(:new).with("/?foo=bar", base_headers).and_return(request_mock) - rest.request(:DELETE, url) - end - - it "should raise an error if the method is not GET/PUT/POST/DELETE" do - expect { rest.request(:MONKEY, url) }.to raise_error(ArgumentError) - end - - it "returns nil when the response is successful but content-type is not JSON" do - expect(rest.request(:GET, url)).to eq("ninja") - end - - it "should fail if the response is truncated" do - http_response["Content-Length"] = (body.bytesize + 99).to_s - expect { rest.request(:GET, url) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - - context "when JSON is returned" do - let(:body) { '{"ohai2u":"json_api"}' } - it "should inflate the body as to an object" do - http_response.add_field("content-type", "application/json") - expect(rest.request(:GET, url, {})).to eq({ "ohai2u" => "json_api" }) - end - - it "should fail if the response is truncated" do - http_response.add_field("content-type", "application/json") - http_response["Content-Length"] = (body.bytesize + 99).to_s - expect { rest.request(:GET, url, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - end - - %w{ HTTPFound HTTPMovedPermanently HTTPSeeOther HTTPUseProxy HTTPTemporaryRedirect HTTPMultipleChoice }.each do |resp_name| - describe "when encountering a #{resp_name} redirect" do - let(:http_response) do - resp_cls = Net.const_get(resp_name) - resp_code = Net::HTTPResponse::CODE_TO_OBJ.keys.detect { |k| Net::HTTPResponse::CODE_TO_OBJ[k] == resp_cls } - http_response = Net::HTTPFound.new("1.1", resp_code, "bob is somewhere else again") - http_response.add_field("location", url.path) - allow(http_response).to receive(:read_body) - http_response - end - it "should call request again" do - - expect { rest.request(:GET, url) }.to raise_error(Chef::Exceptions::RedirectLimitExceeded) - - [:PUT, :POST, :DELETE].each do |method| - expect { rest.request(method, url) }.to raise_error(Chef::Exceptions::InvalidRedirect) - end - end - end - end - - context "when the response is 304 NotModified" do - let (:http_response) do - http_response = Net::HTTPNotModified.new("1.1", "304", "it's the same as when you asked 5 minutes ago") - allow(http_response).to receive(:read_body) - http_response - end - - it "should return `false`" do - expect(rest.request(:GET, url)).to be_falsey - end - end - - describe "when the request fails" do - before do - @original_log_level = Chef::Log.level - Chef::Log.level = :info - end - - after do - Chef::Log.level = @original_log_level - end - - context "on an unsuccessful response with a JSON error" do - let(:http_response) do - http_response = Net::HTTPServerError.new("1.1", "500", "drooling from inside of mouth") - http_response.add_field("content-type", "application/json") - allow(http_response).to receive(:body).and_return('{ "error":[ "Ears get sore!", "Not even four" ] }') - allow(http_response).to receive(:read_body) - http_response - end - - it "should show the JSON error message" do - allow(rest).to receive(:sleep) - - expect { rest.request(:GET, url) }.to raise_error(Net::HTTPFatalError) - expect(log_stringio.string).to match(Regexp.escape("INFO: HTTP Request Returned 500 drooling from inside of mouth: Ears get sore!, Not even four")) - end - end - - context "on an unsuccessful response with a JSON error that is compressed" do - let(:http_response) do - http_response = Net::HTTPServerError.new("1.1", "500", "drooling from inside of mouth") - http_response.add_field("content-type", "application/json") - http_response.add_field("content-encoding", "deflate") - unzipped_body = '{ "error":[ "Ears get sore!", "Not even four" ] }' - gzipped_body = Zlib::Deflate.deflate(unzipped_body) - gzipped_body.force_encoding(Encoding::BINARY) if "strings".respond_to?(:force_encoding) - - allow(http_response).to receive(:body).and_return gzipped_body - allow(http_response).to receive(:read_body) - http_response - end - - before do - allow(rest).to receive(:sleep) - allow(rest).to receive(:http_retry_count).and_return(0) - end - - it "decompresses the JSON error message" do - expect { rest.request(:GET, url) }.to raise_error(Net::HTTPFatalError) - expect(log_stringio.string).to match(Regexp.escape("INFO: HTTP Request Returned 500 drooling from inside of mouth: Ears get sore!, Not even four")) - end - - it "fails when the compressed body is truncated" do - http_response["Content-Length"] = (body.bytesize + 99).to_s - expect { rest.request(:GET, url) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - end - - context "on a generic unsuccessful request" do - let(:http_response) do - http_response = Net::HTTPServerError.new("1.1", "500", "drooling from inside of mouth") - allow(http_response).to receive(:body) - allow(http_response).to receive(:read_body) - http_response - end - - it "retries then throws an exception" do - allow(rest).to receive(:sleep) - expect { rest.request(:GET, url) }.to raise_error(Net::HTTPFatalError) - count = Chef::Config[:http_retry_count] - expect(log_stringio.string).to match(Regexp.escape("ERROR: Server returned error 500 for #{url}, retrying #{count}/#{count}")) - end - end - end - end # as JSON API requests - - context "when streaming downloads to a tempfile" do - let!(:tempfile) { Tempfile.open("chef-rspec-rest_spec-line-@{__LINE__}--") } - - let(:request_mock) { {} } - - let(:http_response) do - http_response = Net::HTTPSuccess.new("1.1", "200", "it-works") - - allow(http_response).to receive(:read_body) - expect(http_response).not_to receive(:body) - http_response["Content-Length"] = "0" # call set_content_length (in test), if otherwise - http_response - end - - def set_content_length - content_length = 0 - http_response.read_body do |chunk| - content_length += chunk.bytesize - end - http_response["Content-Length"] = content_length.to_s - end - - before do - allow(Tempfile).to receive(:new).with("chef-rest").and_return(tempfile) - allow(Net::HTTP::Get).to receive(:new).and_return(request_mock) - end - - after do - tempfile.close! - end - - it " build a new HTTP GET request without the application/json accept header" do - expected_headers = { "Accept" => "*/*", - "X-Chef-Version" => Chef::VERSION, - "Accept-Encoding" => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE, - "Host" => host_header, - "X-REMOTE-REQUEST-ID" => request_id, - "X-Ops-Server-API-Version" => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION, - } - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", expected_headers).and_return(request_mock) - rest.streaming_request(url, {}) - end - - it "build a new HTTP GET request with the X-Remote-Request-Id header" do - expected_headers = { "Accept" => "*/*", - "X-Chef-Version" => Chef::VERSION, - "Accept-Encoding" => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE, - "Host" => host_header, - "X-REMOTE-REQUEST-ID" => request_id, - "X-Ops-Server-API-Version" => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION, - } - expect(Net::HTTP::Get).to receive(:new).with("/?foo=bar", expected_headers).and_return(request_mock) - rest.streaming_request(url, {}) - end - - it "returns a tempfile containing the streamed response body" do - expect(rest.streaming_request(url, {})).to equal(tempfile) - end - - it "writes the response body to a tempfile" do - allow(http_response).to receive(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") - set_content_length - rest.streaming_request(url, {}) - expect(IO.read(tempfile.path).chomp).to eq("realultimatepower") - end - - it "closes the tempfile" do - rest.streaming_request(url, {}) - expect(tempfile).to be_closed - end - - it "yields the tempfile containing the streamed response body and then unlinks it when given a block" do - allow(http_response).to receive(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") - set_content_length - tempfile_path = nil - rest.streaming_request(url, {}) do |tempfile| - tempfile_path = tempfile.path - expect(File.exist?(tempfile.path)).to be_truthy - expect(IO.read(tempfile.path).chomp).to eq("realultimatepower") - end - expect(File.exist?(tempfile_path)).to be_falsey - end - - it "does not raise a divide by zero exception if the content's actual size is 0" do - http_response["Content-Length"] = "5" - allow(http_response).to receive(:read_body).and_yield("") - expect { rest.streaming_request(url, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - - it "does not raise a divide by zero exception when the Content-Length is 0" do - http_response["Content-Length"] = "0" - allow(http_response).to receive(:read_body).and_yield("ninja") - expect { rest.streaming_request(url, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - - it "it raises an exception when the download is truncated" do - http_response["Content-Length"] = (body.bytesize + 99).to_s - allow(http_response).to receive(:read_body).and_yield("ninja") - expect { rest.streaming_request(url, {}) }.to raise_error(Chef::Exceptions::ContentLengthMismatch) - end - - it "fetches a file and yields the tempfile it is streamed to" do - allow(http_response).to receive(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") - set_content_length - tempfile_path = nil - rest.fetch("cookbooks/a_cookbook") do |tempfile| - tempfile_path = tempfile.path - expect(IO.read(tempfile.path).chomp).to eq("realultimatepower") - end - expect(File.exist?(tempfile_path)).to be_falsey - end - - it "closes and unlinks the tempfile if there is an error while streaming the content to the tempfile" do - path = tempfile.path - expect(path).not_to be_nil - allow(tempfile).to receive(:write).and_raise(IOError) - rest.fetch("cookbooks/a_cookbook") { |tmpfile| "shouldn't get here" } - expect(File.exists?(path)).to be_falsey - end - - it "closes and unlinks the tempfile when the response is a redirect" do - tempfile = double("A tempfile", :path => "/tmp/ragefist", :close => true, :binmode => true) - expect(tempfile).to receive(:close!).at_least(1).times - allow(Tempfile).to receive(:new).with("chef-rest").and_return(tempfile) - - redirect = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") - redirect.add_field("location", url.path) - allow(redirect).to receive(:read_body) - - expect(http_client).to receive(:request).and_yield(redirect).and_return(redirect) - expect(http_client).to receive(:request).and_yield(http_response).and_return(http_response) - rest.fetch("cookbooks/a_cookbook") { |tmpfile| "shouldn't get here" } - end - - it "passes the original block to the redirected request" do - http_redirect = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") - http_redirect.add_field("location", "/that-thing-is-here-now") - allow(http_redirect).to receive(:read_body) - - block_called = false - allow(http_client).to receive(:request).and_yield(http_response).and_return(http_redirect, http_response) - rest.fetch("cookbooks/a_cookbook") do |tmpfile| - block_called = true - end - expect(block_called).to be_truthy - end - end - end # when making REST requests - - context "when following redirects" do - let(:rest) do - Chef::REST.new(base_url) - end - - before do - Chef::Config[:node_name] = "webmonkey.example.com" - Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" - end - - it "raises a RedirectLimitExceeded when redirected more than 10 times" do - redirected = lambda { rest.follow_redirect { redirected.call } } - expect { redirected.call }.to raise_error(Chef::Exceptions::RedirectLimitExceeded) - end - - it "does not count redirects from previous calls against the redirect limit" do - total_redirects = 0 - redirected = lambda do - rest.follow_redirect do - total_redirects += 1 - redirected.call unless total_redirects >= 9 - end - end - expect { redirected.call }.not_to raise_error - total_redirects = 0 - expect { redirected.call }.not_to raise_error - end - - it "does not sign the redirected request when sign_on_redirect is false" do - rest.sign_on_redirect = false - rest.follow_redirect { expect(rest.sign_requests?).to be_falsey } - end - - it "resets sign_requests to the original value after following an unsigned redirect" do - rest.sign_on_redirect = false - expect(rest.sign_requests?).to be_truthy - - rest.follow_redirect { expect(rest.sign_requests?).to be_falsey } - expect(rest.sign_requests?).to be_truthy - end - - it "configures the redirect limit" do - total_redirects = 0 - redirected = lambda do - rest.follow_redirect do - total_redirects += 1 - redirected.call unless total_redirects >= 9 - end - end - expect { redirected.call }.not_to raise_error - - total_redirects = 0 - rest.redirect_limit = 3 - expect { redirected.call }.to raise_error(Chef::Exceptions::RedirectLimitExceeded) - end - - end -end diff --git a/spec/unit/runner_spec.rb b/spec/unit/runner_spec.rb index 4e7f4d6671..ea721965c7 100644 --- a/spec/unit/runner_spec.rb +++ b/spec/unit/runner_spec.rb @@ -1,6 +1,6 @@ # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -98,25 +98,6 @@ describe Chef::Runner do run_context.resource_collection << first_resource end - context "when we fall through to old Chef::Platform resolution" do - let(:provider_resolver) { Chef::ProviderResolver.new(node, first_resource, nil) } - before do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - # set up old Chef::Platform resolution instead of provider_resolver - Chef::Platform.set( - :resource => :cat, - :provider => Chef::Provider::SnakeOil - ) - allow(Chef::ProviderResolver).to receive(:new).and_return(provider_resolver) - allow(provider_resolver).to receive(:maybe_dynamic_provider_resolution).with(first_resource, anything()).and_return(nil) - end - - it "should use the platform provider if it has one" do - expect(Chef::Platform).to receive(:find_provider_for_node).with(node, first_resource).and_call_original - runner.converge - end - end - context "when we are doing dynamic provider resolution" do it "should pass each resource in the collection to a provider" do diff --git a/spec/unit/search/query_spec.rb b/spec/unit/search/query_spec.rb index 6df8587717..0837410b3c 100644 --- a/spec/unit/search/query_spec.rb +++ b/spec/unit/search/query_spec.rb @@ -24,7 +24,7 @@ describe Chef::Search::Query do let(:query) { Chef::Search::Query.new } shared_context "filtered search" do - let(:query_string) { "search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=0" } + let(:query_string) { "search/node?q=platform:rhel&start=0" } let(:server_url) { "https://api.opscode.com/organizations/opscode/nodes" } let(:args) { { filter_key => filter_hash } } let(:filter_hash) do @@ -81,10 +81,10 @@ describe Chef::Search::Query do end describe "search" do - let(:query_string) { "search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=0" } - let(:query_string_continue) { "search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=4" } - let(:query_string_with_rows) { "search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=0&rows=4" } - let(:query_string_continue_with_rows) { "search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=4&rows=4" } + let(:query_string) { "search/node?q=platform:rhel&start=0" } + let(:query_string_continue) { "search/node?q=platform:rhel&start=4" } + let(:query_string_with_rows) { "search/node?q=platform:rhel&start=0&rows=4" } + let(:query_string_continue_with_rows) { "search/node?q=platform:rhel&start=4&rows=4" } let(:response) do { @@ -178,27 +178,22 @@ describe Chef::Search::Query do end it "queries for every object of a type by default" do - expect(rest).to receive(:get).with("search/node?q=*:*&sort=X_CHEF_id_CHEF_X%20asc&start=0").and_return(response) + expect(rest).to receive(:get).with("search/node?q=*:*&start=0").and_return(response) query.search(:node) end it "allows a custom query" do - expect(rest).to receive(:get).with("search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=0").and_return(response) + expect(rest).to receive(:get).with("search/node?q=platform:rhel&start=0").and_return(response) query.search(:node, "platform:rhel") end - it "lets you set a sort order" do - expect(rest).to receive(:get).with("search/node?q=platform:rhel&sort=id%20desc&start=0").and_return(response) - query.search(:node, "platform:rhel", sort: "id desc") - end - it "lets you set a starting object" do - expect(rest).to receive(:get).with("search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=2").and_return(response) + expect(rest).to receive(:get).with("search/node?q=platform:rhel&start=2").and_return(response) query.search(:node, "platform:rhel", start: 2) end it "lets you set how many rows to return" do - expect(rest).to receive(:get).with("search/node?q=platform:rhel&sort=X_CHEF_id_CHEF_X%20asc&start=0&rows=40").and_return(response) + expect(rest).to receive(:get).with("search/node?q=platform:rhel&start=0&rows=40").and_return(response) query.search(:node, "platform:rhel", rows: 40) end @@ -223,7 +218,7 @@ describe Chef::Search::Query do it "pages through the responses" do @call_me = double("blocky") response["rows"].each { |r| expect(@call_me).to receive(:do).with(Chef::Node.from_hash(r)) } - query.search(:node, "*:*", sort: nil, start: 0, rows: 4) { |r| @call_me.do(r) } + query.search(:node, "*:*", start: 0, rows: 4) { |r| @call_me.do(r) } end it "sends multiple API requests when the server indicates there is more data" do diff --git a/spec/unit/shell/shell_session_spec.rb b/spec/unit/shell/shell_session_spec.rb index 259e6096a4..170767fbd6 100644 --- a/spec/unit/shell/shell_session_spec.rb +++ b/spec/unit/shell/shell_session_spec.rb @@ -77,6 +77,37 @@ describe Shell::ClientSession do end +describe Shell::SoloSession do + before do + Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new("shell::override")] } + @chef_rest = double("Chef::ServerAPI") + @session = Shell::SoloSession.instance + @node = Chef::Node.build("foo") + @session.node = @node + @client = double("Chef::Client.new", + :run_ohai => true, + :load_node => true, + :build_node => true, + :register => true, + :sync_cookbooks => {}) + end + + it "builds the node's run_context with the proper environment" do + @session.instance_variable_set(:@client, @client) + @expansion = Chef::RunList::RunListExpansion.new(@node.chef_environment, []) + + expect(@node.run_list).to receive(:expand).with(@node.chef_environment).and_return(@expansion) + expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(@chef_rest) + @session.rebuild_context + end + + it "passes the shell CLI args to the client" do + expect(Chef::Client).to receive(:new).with(nil, Chef::Config[:shell_config]).and_return(@client) + @session.send(:rebuild_node) + end + +end + describe Shell::StandAloneSession do before do Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new("shell::override")] } @@ -128,11 +159,11 @@ describe Shell::StandAloneSession do end -describe Shell::SoloSession do +describe Shell::SoloLegacySession do before do Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new("shell::override")] } Chef::Config[:shell_solo] = true - @session = Shell::SoloSession.instance + @session = Shell::SoloLegacySession.instance @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = @session.run_context = Chef::RunContext.new(@node, {}, @events) diff --git a/spec/unit/shell_out_spec.rb b/spec/unit/shell_out_spec.rb deleted file mode 100644 index 35844f4961..0000000000 --- a/spec/unit/shell_out_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require File.expand_path("../../spec_helper", __FILE__) - -describe "Chef::ShellOut deprecation notices" do - it "logs a warning when initializing a new Chef::ShellOut object" do - expect(Chef::Log).to receive(:warn).with("Chef::ShellOut is deprecated, please use Mixlib::ShellOut") - expect(Chef::Log).to receive(:warn).with(/Called from\:/) - Chef::ShellOut.new("pwd") - end -end - -describe "Chef::Exceptions::ShellCommandFailed deprecation notices" do - - it "logs a warning when referencing the constant Chef::Exceptions::ShellCommandFailed" do - expect(Chef::Log).to receive(:warn).with("Chef::Exceptions::ShellCommandFailed is deprecated, use Mixlib::ShellOut::ShellCommandFailed") - expect(Chef::Log).to receive(:warn).with(/Called from\:/) - Chef::Exceptions::ShellCommandFailed - end -end |