summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhishekKr <abhikumar163@gmail.com>2016-07-31 07:42:10 +0530
committerAbhishekKr <abhikumar163@gmail.com>2016-07-31 07:42:10 +0530
commitc3c6cfc156d0a0bfe7c7dd4f273a2c2bdc4b0281 (patch)
treecafccae761432edd05c952f5c8fdb452bfd30ad5
parent58e147a9dfa331c359df2c9a2bcc53a27a722ef5 (diff)
parent6b88d8c1bd89f9864478fc873352c2881441dbfe (diff)
downloadchef-c3c6cfc156d0a0bfe7c7dd4f273a2c2bdc4b0281.tar.gz
Merge branch 'master' of https://github.com/chef/chef
-rw-r--r--CHANGELOG.md35
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock98
-rw-r--r--RELEASE_NOTES.md64
-rw-r--r--VERSION2
-rw-r--r--acceptance/.gitignore2
-rw-r--r--acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml13
-rw-r--r--acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb41
-rw-r--r--acceptance/Gemfile9
-rw-r--r--acceptance/Gemfile.lock172
-rw-r--r--acceptance/data-collector/Berksfile.lock6
-rw-r--r--acceptance/data-collector/test/integration/default/serverspec/default_spec.rb43
-rw-r--r--acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb4
-rw-r--r--acceptance/trivial/.kitchen.yml2
-rw-r--r--acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/destroy.rb2
-rw-r--r--acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/provision.rb2
-rw-r--r--acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/verify.rb2
-rw-r--r--acceptance/windows-service/test/integration/chef-windows-service/inspec/chef_windows_service_spec.rb8
-rw-r--r--chef-config/lib/chef-config/config.rb4
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef.gemspec7
-rw-r--r--kitchen-tests/.kitchen.travis.yml1
-rw-r--r--kitchen-tests/.kitchen.yml1
-rw-r--r--kitchen-tests/Berksfile.lock6
-rw-r--r--kitchen-tests/Gemfile.lock98
-rw-r--r--lib/chef/application.rb4
-rw-r--r--lib/chef/application/client.rb4
-rw-r--r--lib/chef/application/solo.rb4
-rw-r--r--lib/chef/audit/runner.rb2
-rw-r--r--lib/chef/chef_fs/file_system/repository/directory.rb6
-rw-r--r--lib/chef/chef_fs/file_system_cache.rb62
-rw-r--r--lib/chef/data_collector.rb20
-rw-r--r--lib/chef/data_collector/messages.rb31
-rw-r--r--lib/chef/data_collector/resource_report.rb20
-rw-r--r--lib/chef/decorator/unchain.rb59
-rw-r--r--lib/chef/dsl/cheffish.rb1
-rw-r--r--lib/chef/dsl/declare_resource.rb10
-rw-r--r--lib/chef/exceptions.rb5
-rw-r--r--lib/chef/http.rb10
-rw-r--r--lib/chef/knife/bootstrap.rb1
-rw-r--r--lib/chef/knife/cookbook_site_install.rb13
-rw-r--r--lib/chef/knife/cookbook_site_share.rb20
-rw-r--r--lib/chef/node.rb45
-rw-r--r--lib/chef/node/attribute.rb193
-rw-r--r--lib/chef/node/attribute_collections.rb139
-rw-r--r--lib/chef/node/common_api.rb129
-rw-r--r--lib/chef/node/immutable_collections.rb29
-rw-r--r--lib/chef/property.rb8
-rw-r--r--lib/chef/provider/batch.rb2
-rw-r--r--lib/chef/provider/file.rb8
-rw-r--r--lib/chef/provider/package/aix.rb6
-rw-r--r--lib/chef/provider/package/openbsd.rb2
-rw-r--r--lib/chef/provider/package/zypper.rb14
-rw-r--r--lib/chef/provider/powershell_script.rb2
-rw-r--r--lib/chef/resource.rb14
-rw-r--r--lib/chef/resource_builder.rb6
-rw-r--r--lib/chef/run_context.rb57
-rw-r--r--lib/chef/shell.rb2
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus/Gemfile.lock30
-rw-r--r--pkg.rb1
-rw-r--r--rubygems-pkg/rubygems-update-2.4.6.gembin451072 -> 0 bytes
-rw-r--r--spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb6
-rw-r--r--spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb5
-rw-r--r--spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb4
-rw-r--r--spec/data/run_context/cookbooks/dependency1/attributes/default.rb4
-rw-r--r--spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb5
-rw-r--r--spec/data/run_context/cookbooks/dependency2/attributes/default.rb5
-rw-r--r--spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb5
-rw-r--r--spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb5
-rw-r--r--spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb5
-rw-r--r--spec/functional/resource/package_spec.rb2
-rw-r--r--spec/functional/resource/template_spec.rb6
-rw-r--r--spec/functional/shell_spec.rb2
-rw-r--r--spec/integration/knife/diff_spec.rb4
-rw-r--r--spec/integration/knife/download_spec.rb8
-rw-r--r--spec/integration/knife/raw_spec.rb2
-rw-r--r--spec/integration/knife/upload_spec.rb6
-rw-r--r--spec/spec_helper.rb6
-rw-r--r--spec/support/platform_helpers.rb4
-rw-r--r--spec/support/shared/integration/knife_support.rb4
-rw-r--r--spec/support/shared/unit/provider/file.rb25
-rw-r--r--spec/unit/application/solo_spec.rb12
-rw-r--r--spec/unit/cookbook_version_spec.rb8
-rw-r--r--spec/unit/data_collector/messages_spec.rb62
-rw-r--r--spec/unit/data_collector_spec.rb42
-rw-r--r--spec/unit/dsl/declare_resource_spec.rb30
-rw-r--r--spec/unit/knife/cookbook_site_install_spec.rb2
-rw-r--r--spec/unit/knife/cookbook_site_share_spec.rb8
-rw-r--r--spec/unit/node/attribute_spec.rb16
-rw-r--r--spec/unit/node/immutable_collections_spec.rb4
-rw-r--r--spec/unit/node/vivid_mash_spec.rb377
-rw-r--r--spec/unit/node_spec.rb171
-rw-r--r--spec/unit/provider/package/aix_spec.rb13
-rw-r--r--spec/unit/provider/package/zypper_spec.rb20
-rw-r--r--spec/unit/provider/powershell_script_spec.rb8
-rw-r--r--spec/unit/recipe_spec.rb21
-rw-r--r--spec/unit/run_context_spec.rb4
-rw-r--r--spec/unit/shell/shell_session_spec.rb2
99 files changed, 1670 insertions, 831 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 549b63abba..c9b30edba7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,40 @@
# Change Log
+## [v12.12.15](https://github.com/chef/chef/tree/v12.12.15) (2016-07-08)
+[Full Changelog](https://github.com/chef/chef/compare/v12.12.13...v12.12.15)
+
+**Fixed Bugs:**
+
+- Fix for #5094 12.12.13 node.default_unless issue [\#5097](https://github.com/chef/chef/pull/5097) ([lamont-granquist](https://github.com/lamont-granquist))
+
+## [v12.12.13](https://github.com/chef/chef/tree/v12.12.13) (2016-07-01)
+[Full Changelog](https://github.com/chef/chef/compare/v12.11.18...v12.12.13)
+
+**Implemented Enhancements:**
+
+- Tweak 3694 warnings [\#5075](https://github.com/chef/chef/pull/5075) ([lamont-granquist](https://github.com/lamont-granquist))
+- Adding node object to Data collector run\_converge message [\#5065](https://github.com/chef/chef/pull/5065) ([adamleff](https://github.com/adamleff))
+- Attribute API improvements [\#5029](https://github.com/chef/chef/pull/5029) ([lamont-granquist](https://github.com/lamont-granquist))
+- Remove deprecated Thread.exclusive around require call. [\#5068](https://github.com/chef/chef/pull/5068) ([maxlazio](https://github.com/maxlazio))
+- Ensure that chef-solo uses the expected repo dir [\#5059](https://github.com/chef/chef/pull/5059) ([thommay](https://github.com/thommay))
+- Expand data\_collector resource list to include all resources [\#5058](https://github.com/chef/chef/pull/5058) ([adamleff](https://github.com/adamleff))
+- Turn off fips with an empty environment var [\#5048](https://github.com/chef/chef/pull/5048) ([mwrock](https://github.com/mwrock))
+- Deprecate knife-supermarket gem [\#4896](https://github.com/chef/chef/pull/4896) ([thommay](https://github.com/thommay))
+- Update Nokogiri [\#5042](https://github.com/chef/chef/pull/5042) ([mwrock](https://github.com/mwrock))
+- Remote resource should respect sensitive flag [\#5025](https://github.com/chef/chef/pull/5025) ([PrajaktaPurohit](https://github.com/PrajaktaPurohit))
+- Convert the 3694 warning to a deprecation so it will be subject to the usual deprecation formatting \(collected at the bottom, can be made an error, etc\). [\#5022](https://github.com/chef/chef/pull/5022) ([coderanger](https://github.com/coderanger))
+- Deprecate `knife cookbook create` in favor of `chef generate cookbook`. [\#5021](https://github.com/chef/chef/pull/5021) ([tylercloke](https://github.com/tylercloke))
+
+**Fixed Bugs:**
+
+- Fixes windows_package uninstall scenarios by calling uninstall string directly [\#5050](https://github.com/chef/chef/pull/5050) ([mwrock](https://github.com/mwrock))
+- Fix gem_package idempotency [\#5046](https://github.com/chef/chef/pull/5046) ([thommay](https://github.com/thommay))
+- Undefined local variable lookup in multiplexed_dir.rb [\#5027](https://github.com/chef/chef/issues/5027) ([robdimarco](https://github.com/robdimarco))
+- Correctly write out data collector metadata file [\#5019](https://github.com/chef/chef/pull/5019) ([adamleff](https://github.com/adamleff))
+- Eliminate missing constant errors for LWRP class [\#5000](https://github.com/chef/chef/pull/5000) ([PrajaktaPurohit](https://github.com/PrajaktaPurohit))
+- Updated_resource_count to data collector should only include updated resources [\#5006](https://github.com/chef/chef/pull/5006) ([adamleff](https://github.com/adamleff))
+- Don't mask directory deletion errors [\#4991](https://github.com/chef/chef/pull/4991) ([jaymzh](https://github.com/jaymzh))
+
## [v12.11.18](https://github.com/chef/chef/tree/v12.11.18) (2016-06-02)
[Full Changelog](https://github.com/chef/chef/compare/v12.11.17...v12.11.18)
diff --git a/Gemfile b/Gemfile
index e2f4555af1..9327fb539a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -20,6 +20,7 @@ gem "cheffish"
group(:omnibus_package) do
gem "appbundler"
gem "rb-readline"
+ gem "nokogiri"
end
group(:omnibus_package, :pry) do
@@ -65,7 +66,7 @@ end
group(:development, :test) do
gem "simplecov"
- gem "rack"
+ gem "rack", "< 2.0" # 2.0 requires Ruby 2.2+
# for testing new chefstyle rules
# gem 'chefstyle', github: 'chef/chefstyle'
diff --git a/Gemfile.lock b/Gemfile.lock
index 7d166cb74d..215b5326ce 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -17,17 +17,18 @@ GIT
PATH
remote: .
specs:
- chef (12.12.7)
+ chef (12.13.16)
bundler (>= 1.10)
- chef-config (= 12.12.7)
- chef-zero (~> 4.5)
+ chef-config (= 12.13.16)
+ chef-zero (~> 4.8)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
+ mixlib-archive (>= 0.2.0)
mixlib-authentication (~> 1.4)
- mixlib-cli (~> 1.4)
+ mixlib-cli (~> 1.4, < 1.7)
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
@@ -36,26 +37,27 @@ PATH
ohai (>= 8.6.0.alpha.1, < 9)
plist (~> 3.2)
proxifier (~> 1.0)
- rspec-core (~> 3.4)
- rspec-expectations (~> 3.4)
- rspec-mocks (~> 3.4)
+ rspec-core (~> 3.5)
+ rspec-expectations (~> 3.5)
+ rspec-mocks (~> 3.5)
rspec_junit_formatter (~> 0.2.0)
serverspec (~> 2.7)
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (12.12.7-universal-mingw32)
+ chef (12.13.16-universal-mingw32)
bundler (>= 1.10)
- chef-config (= 12.12.7)
- chef-zero (~> 4.5)
+ chef-config (= 12.13.16)
+ chef-zero (~> 4.8)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
+ mixlib-archive (>= 0.2.0)
mixlib-authentication (~> 1.4)
- mixlib-cli (~> 1.4)
+ mixlib-cli (~> 1.4, < 1.7)
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
@@ -64,9 +66,9 @@ PATH
ohai (>= 8.6.0.alpha.1, < 9)
plist (~> 3.2)
proxifier (~> 1.0)
- rspec-core (~> 3.4)
- rspec-expectations (~> 3.4)
- rspec-mocks (~> 3.4)
+ rspec-core (~> 3.5)
+ rspec-expectations (~> 3.5)
+ rspec-mocks (~> 3.5)
rspec_junit_formatter (~> 0.2.0)
serverspec (~> 2.7)
specinfra (~> 2.10)
@@ -86,7 +88,7 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (12.12.7)
+ chef-config (12.13.16)
fuzzyurl (~> 0.8.0)
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
@@ -97,14 +99,14 @@ GEM
addressable (2.4.0)
appbundler (0.9.0)
mixlib-cli (~> 1.4)
- artifactory (2.3.2)
+ artifactory (2.3.3)
ast (2.3.0)
- aws-sdk (2.3.16)
- aws-sdk-resources (= 2.3.16)
- aws-sdk-core (2.3.16)
+ aws-sdk (2.3.19)
+ aws-sdk-resources (= 2.3.19)
+ aws-sdk-core (2.3.19)
jmespath (~> 1.0)
- aws-sdk-resources (2.3.16)
- aws-sdk-core (= 2.3.16)
+ aws-sdk-resources (2.3.19)
+ aws-sdk-core (= 2.3.19)
aws-sdk-v1 (1.66.0)
json (~> 1.4)
nokogiri (>= 1.4.4)
@@ -131,11 +133,11 @@ GEM
ubuntu_ami (~> 0.4, >= 0.4.1)
chef-rewind (0.0.9)
chef-sugar (3.3.0)
- chef-zero (4.6.2)
+ chef-zero (4.8.0)
ffi-yajl (~> 2.2)
hashie (>= 2.0, < 4.0)
mixlib-log (~> 1.3)
- rack
+ rack (< 2)
uuidtools (~> 2.1)
cheffish (2.0.4)
chef-zero (~> 4.3)
@@ -145,7 +147,7 @@ GEM
fauxhai (~> 3.2)
rspec (~> 3.0)
coderay (1.1.1)
- colorize (0.7.7)
+ colorize (0.8.1)
compat_resource (12.10.6)
cucumber-core (1.5.0)
gherkin (~> 4.0)
@@ -157,10 +159,12 @@ GEM
erubis (2.7.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- fauxhai (3.5.0)
+ fauxhai (3.6.0)
net-ssh
ffi (1.9.10)
ffi (1.9.10-x86-mingw32)
+ ffi-win32-extensions (1.0.2)
+ ffi
ffi-yajl (2.2.3)
libyajl2 (~> 1.2)
foodcritic (6.3.0)
@@ -173,7 +177,7 @@ GEM
yajl-ruby (~> 1.1)
fuzzyurl (0.8.0)
gherkin (4.0.0)
- github_api (0.14.1)
+ github_api (0.14.2)
addressable (~> 2.4.0)
descendants_tracker (~> 0.0.4)
faraday (~> 0.8, < 0.10)
@@ -187,10 +191,10 @@ GEM
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- halite (1.2.1)
+ halite (1.3.0)
bundler
chef (~> 12.0)
- stove (~> 3.2, >= 3.2.3)
+ stove (~> 4.0)
thor
hashie (3.4.4)
highline (1.7.8)
@@ -216,11 +220,13 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
+ mixlib-archive (0.2.0)
+ mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
mixlib-cli (1.6.0)
mixlib-config (2.2.1)
- mixlib-install (1.0.13)
+ mixlib-install (1.1.0)
artifactory
mixlib-shellout
mixlib-versioning
@@ -260,7 +266,7 @@ GEM
rack (>= 1.2, < 3)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
- ohai (8.17.0)
+ ohai (8.17.1)
chef-config (>= 12.5.0.alpha.1, < 13)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
@@ -299,22 +305,22 @@ GEM
rake (11.2.2)
rb-readline (0.5.3)
retryable (2.0.3)
- rspec (3.4.0)
- rspec-core (~> 3.4.0)
- rspec-expectations (~> 3.4.0)
- rspec-mocks (~> 3.4.0)
- rspec-core (3.4.4)
- rspec-support (~> 3.4.0)
- rspec-expectations (3.4.0)
+ rspec (3.5.0)
+ rspec-core (~> 3.5.0)
+ rspec-expectations (~> 3.5.0)
+ rspec-mocks (~> 3.5.0)
+ rspec-core (3.5.1)
+ rspec-support (~> 3.5.0)
+ rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
+ rspec-support (~> 3.5.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.4.1)
+ rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
- rspec-support (3.4.1)
+ rspec-support (~> 3.5.0)
+ rspec-support (3.5.0)
rspec_junit_formatter (0.2.3)
builder (< 4)
rspec-core (>= 2, < 4, != 2.12.0)
@@ -344,12 +350,12 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
slop (3.6.0)
- specinfra (2.59.3)
+ specinfra (2.59.4)
net-scp
net-ssh (>= 2.7, < 4.0)
net-telnet
sfl
- stove (3.2.8)
+ stove (4.1.1)
chef-api (~> 0.5)
logify (~> 0.2)
syslog-logger (1.6.8)
@@ -377,8 +383,9 @@ GEM
win32-ipc (>= 0.6.0)
win32-process (0.8.3)
ffi (>= 1.0.0)
- win32-service (0.8.7)
+ win32-service (0.8.9)
ffi
+ ffi-win32-extensions
windows-api (0.4.4)
win32-api (>= 1.4.5)
winrm (1.8.1)
@@ -415,13 +422,14 @@ DEPENDENCIES
halite
knife-windows
netrc
+ nokogiri
octokit
poise
pry
pry-byebug
pry-remote
pry-stack_explorer
- rack
+ rack (< 2.0)
rake
rb-readline
ruby-prof
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 4d99cec89f..b3bba87dc0 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,57 +1,35 @@
*This file holds "in progress" release notes for the current release under development and is intended for consumption by the Chef Documentation team.
Please see `https://docs.chef.io/release/<major>-<minor>/release_notes.html` for the official Chef release notes.*
-# Chef Client Release Notes 12.11:
+# Chef Client Release Notes 12.12:
-## Support for RFC 062-based exit codes
+## Attribute read/write/unlink/exist? APIs
-[Chef RFC 062](https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) identifies standard exit codes for Chef Client. As of this release, When Chef exits with a non-standard exit code, a deprecation warning will be printed.
+On the node object:
-Also introduced is a new configuration setting - `exit_status`.
+- `node.read("foo", "bar", "baz")` equals `node["foo"]["bar"]["baz"] `but with safety (nil instead of exception)
+- `node.read!("foo", "bar", "baz")` equals `node["foo"]["bar"]["baz"]` and does raises NoMethodError
-By default in this release, `exit_status` is `nil` and the default behavior will be to warn on the use of deprecated and non-standard exit codes. `exit_status` can be set to `:enabled`, which will force chef-client to exit with the RFC defined exit codes and any non-standard exit statuses will be converted to `1` or GENERIC_FAILURE. `exit_status` can also be set to `:disabled` which preserves the old behavior of non-standardized exit status and skips the deprecation warnings.
+- `node.write(:default, "foo", "bar", "baz")` equals `node.default["foo"]["bar"] = "baz"` and autovivifies and replaces intermediate non-hash objects (very safe)
+- `node.write!(:default, "foo", "bar", "baz")` equals `node.default["foo"]["bar"] = "baz"` and while it autovivifies it can raise if you hit a non-hash on an intermediate key (NoMethodError)
+- there is still no non-autovivifying writer, and i don't think anyone really wants one.
+- `node.exist?("foo", "bar")` can be used to see if `node["foo"]["bar"]` exists
-## New Data Collector functionality for run statistics
+On node levels:
-The Data Collector feature is new to Chef 12.11 and is detailed in [Chef RFC 077](https://github.com/chef/chef-rfc/blob/master/rfc077-mode-agnostic-data-collection.md). It provides a unified method for sharing statistics about your Chef runs in a webhook-like manner. The Data Collector supports Chef in all its modes: Chef Client, Chef Solo (commonly referred to as "Chef Client Local Mode"), and Chef Solo legacy mode.
+- `node.default.read/read!("foo")` operates similarly to `node.read("foo")` but only on default level
+- `node.default.write/write!("foo", "bar")` is `node.write/write!(:default, "foo", "bar")`
+- `node.default.unlink/unlink!("foo")` is `node.unlink/unlink!(:default, "foo")`
+- `node.default.exist?("foo", "bar")` can be used to see if `node.default["foo"]["bar"]` exists
-To enable the Data Collector, specify the following settings in your client configuration file:
+Deprecations:
- * `data_collector.server_url`: Required. The URL to which the Chef Client will POST the Data Collector messages
- * `data_collector.token`: Optional. An token which will be sent in a `x-data-collector-token` HTTP header which can be used to authenticate the message.
- * `data_collector.mode`: The Chef mode in which the Data Collector should run. For example, this allows you to only enable Data Collector in Chef Solo but not Chef Client. Available options are `:solo`, `:client`, or `:both`. Default is `:both`.
- * `data_collector.raise_on_failure`: If enabled, Chef will raise an exception and fail to run if the Data Collector cannot be reached at the start of the Chef run. Defaults to `false`.
- * `data_collector.organization`: Optional. In Solo mode, the `organization` field in the messages will be set to this value. Default is `chef_solo`. This field does not apply to Chef Client mode.
+- node.set is deprecated
+- node.set_unless is deprecated
-## Replace chef-solo with chef-client local mode
+## `data_collector` enhancements
-The default operation of `chef-solo` is now the equivalent to `chef-client -z`, but allows for the old style `chef-solo` by uttering `chef-solo --legacy-mode`. As part of this effort, environment and role files written in ruby are now fully supported by `knife upload`.
+- Adds `node` to the `data_collector` message
+- `data_collector` reports on all resources and not just those that have been processed
-## Added a `systemd_unit` resource
-
-A new `systemd_unit` resource is now available. This resource supports the following properties:
-
-* `enabled` - boolean
-* `active` - boolean
-* `masked` - boolean
-* `static` - boolean
-* `user` - String
-* `content` - String or Hash
-* `triggers_reload` - boolean
-
-It has these possible actions:
-
-* `:nothing` - default
-* `:create`
-* `:delete`
-* `:enable`
-* `:disable`
-* `:mask`
-* `:unmask`
-* `:start`
-* `:stop`
-* `:restart`
-* `:reload`
-* `:try_restart`
-* `:reload_or_restart`
-* `:reload_or_try_restart`
+## `knife cookbook create` is deprecated. Use the chef-dk's `chef generate cookbook` instead. \ No newline at end of file
diff --git a/VERSION b/VERSION
index 5952cee2fe..8fb2f2ff9e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.12.7 \ No newline at end of file
+12.13.16 \ No newline at end of file
diff --git a/acceptance/.gitignore b/acceptance/.gitignore
index c2ab70737d..4b0b151d75 100644
--- a/acceptance/.gitignore
+++ b/acceptance/.gitignore
@@ -1 +1,3 @@
.acceptance_logs
+.acceptance_data
+data-collector/Berksfile.lock
diff --git a/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml b/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
index 40228829bb..dfe3d888a0 100644
--- a/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
+++ b/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
@@ -213,18 +213,7 @@ platforms:
image-type: machine
user_data: |
<powershell>
- $logfile="C:\\Program Files\\Amazon\\Ec2ConfigService\\Logs\\kitchen-ec2.log"
- #PS Remoting and & winrm.cmd basic config
- Enable-PSRemoting -Force -SkipNetworkProfileCheck
- & winrm.cmd set winrm/config '@{MaxTimeoutms="1800000"}' >> $logfile
- & winrm.cmd set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}' >> $logfile
- & winrm.cmd set winrm/config/winrs '@{MaxShellsPerUser="50"}' >> $logfile
- #Server settings - support username/password login
- & winrm.cmd set winrm/config/service/auth '@{Basic="true"}' >> $logfile
- & winrm.cmd set winrm/config/service '@{AllowUnencrypted="true"}' >> $logfile
- & winrm.cmd set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}' >> $logfile
- #Firewall Config
- & netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" profile=public protocol=tcp localport=5985 remoteip=localsubnet new remoteip=any >> $logfile
+ & netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" profile=public protocol=tcp localport=5985 remoteip=localsubnet new remoteip=any
#Set script execution to unrestricted
& Set-ExecutionPolicy Unrestricted -Force
</powershell>
diff --git a/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb b/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb
index d36909e8b3..d5d2e1380b 100644
--- a/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb
+++ b/acceptance/.shared/kitchen_acceptance/libraries/kitchen.rb
@@ -1,3 +1,5 @@
+require 'chef/mixin/shell_out'
+
module KitchenAcceptance
class Kitchen < Chef::Resource
resource_name :kitchen
@@ -33,18 +35,33 @@ module KitchenAcceptance
property :kitchen_options, String, default: lazy { ENV["PROJECT_NAME"] ? "-c -l debug" : "-c" }
action :run do
- execute "bundle exec kitchen #{command}#{instances ? " #{instances}" : ""}#{kitchen_options ? " #{kitchen_options}" : ""}" do
- cwd kitchen_dir
- env({
- "KITCHEN_DRIVER" => driver,
- "KITCHEN_INSTANCES" => instances,
- "KITCHEN_LOCAL_YAML" => ::File.expand_path("../../.kitchen.#{driver}.yml", __FILE__),
- "KITCHEN_CHEF_PRODUCT" => chef_product,
- "KITCHEN_CHEF_CHANNEL" => chef_channel,
- "KITCHEN_CHEF_VERSION" => chef_version,
- "ARTIFACTORY_USERNAME" => artifactory_username,
- "ARTIFACTORY_PASSWORD" => artifactory_password
- }.merge(new_resource.env))
+
+ ruby_block "copy_kitchen_logs_to_data_path" do
+ block do
+ cmd_env = {
+ "KITCHEN_DRIVER" => driver,
+ "KITCHEN_INSTANCES" => instances,
+ "KITCHEN_LOCAL_YAML" => ::File.expand_path("../../.kitchen.#{driver}.yml", __FILE__),
+ "KITCHEN_CHEF_PRODUCT" => chef_product,
+ "KITCHEN_CHEF_CHANNEL" => chef_channel,
+ "KITCHEN_CHEF_VERSION" => chef_version,
+ "ARTIFACTORY_USERNAME" => artifactory_username,
+ "ARTIFACTORY_PASSWORD" => artifactory_password
+ }.merge(new_resource.env)
+ suite = kitchen_dir.split("/").last
+ kitchen_log_path = ENV["WORKSPACE"] ? "#{ENV["WORKSPACE"]}/chef-acceptance-data/logs" : "#{kitchen_dir}/../.acceptance_data/logs/"
+
+ begin
+ shell_out!("bundle exec kitchen #{command}#{instances ? " #{instances}" : ""}#{kitchen_options ? " #{kitchen_options}" : ""}",
+ env: cmd_env,
+ timeout: 60 * 30,
+ live_stream: STDOUT,
+ cwd: kitchen_dir)
+ ensure
+ FileUtils.mkdir_p("#{kitchen_log_path}/#{suite}/#{command}")
+ FileUtils.cp_r("#{kitchen_dir}/.kitchen/logs/.", "#{kitchen_log_path}/#{suite}/#{command}")
+ end
+ end
end
end
end
diff --git a/acceptance/Gemfile b/acceptance/Gemfile
index 185437ed71..b521df8607 100644
--- a/acceptance/Gemfile
+++ b/acceptance/Gemfile
@@ -1,13 +1,16 @@
source "https://rubygems.org"
gem "chef-acceptance", github: "chef/chef-acceptance"
-gem "test-kitchen"
gem "kitchen-ec2"
-gem "kitchen-inspec"
gem "inspec"
# Pinning to github for kitchen-vagrant because 0.19.0 incorrectly
# puts in a box_url for bento when a vagrant box in atlas is specified
gem "kitchen-vagrant"
gem "windows_chef_zero"
-gem "winrm-fs"
+gem "kitchen-inspec", :github => "mwrock/kitchen-inspec", :branch => "winrm-v2"
+gem "test-kitchen", :github => "test-kitchen", :branch => "winrm-v2"
+gem "train", :github => "chef/train", :branch => "winrm-v2"
+gem "winrm", :github => "winrb/winrm", :branch => "winrm-v2"
+gem "winrm-fs", :github => "winrb/winrm-fs", :branch => "winrm-v2"
+gem "winrm-elevated", :github => "winrb/winrm-elevated", :branch => "winrm-v2"
gem "berkshelf"
diff --git a/acceptance/Gemfile.lock b/acceptance/Gemfile.lock
index 6abf73932f..ff9d439b5b 100644
--- a/acceptance/Gemfile.lock
+++ b/acceptance/Gemfile.lock
@@ -6,17 +6,88 @@ GIT
mixlib-shellout (~> 2.0)
thor (~> 0.19)
+GIT
+ remote: git://github.com/chef/train.git
+ revision: cc92f89267f128ee78bc12da803722268e2f6af2
+ branch: winrm-v2
+ specs:
+ train (0.15.0)
+ docker-api (~> 1.26)
+ json (~> 1.8)
+ mixlib-shellout (~> 2.0)
+ net-scp (~> 1.2)
+ net-ssh (>= 2.9, < 4.0)
+ winrm (~> 2.0)
+ winrm-fs (~> 1.0)
+
+GIT
+ remote: git://github.com/mwrock/kitchen-inspec.git
+ revision: d63240a44667974070298ad4fca20394257c92bd
+ branch: winrm-v2
+ specs:
+ kitchen-inspec (0.14.0)
+ inspec (>= 0.22.0, < 1.0.0)
+ test-kitchen (~> 1.6)
+
+GIT
+ remote: git://github.com/test-kitchen/test-kitchen.git
+ revision: 06d7c0168ed6390c87a821ae8958e7d80c4d1912
+ branch: winrm-v2
+ specs:
+ test-kitchen (1.10.2)
+ mixlib-install (~> 1.0, >= 1.0.4)
+ mixlib-shellout (>= 1.2, < 3.0)
+ net-scp (~> 1.1)
+ net-ssh (>= 2.9, < 4.0)
+ safe_yaml (~> 1.0)
+ thor (~> 0.18)
+
+GIT
+ remote: git://github.com/winrb/winrm-elevated.git
+ revision: 160bf424e018b2539fdde73079443e565ae57260
+ branch: winrm-v2
+ specs:
+ winrm-elevated (1.0.0)
+ winrm (~> 2.0)
+ winrm-fs (~> 1.0)
+
+GIT
+ remote: git://github.com/winrb/winrm-fs.git
+ revision: ceb883b87fb81898e73e9249f287457ccb9d549f
+ branch: winrm-v2
+ specs:
+ winrm-fs (1.0.0)
+ erubis (~> 2.7)
+ logging (>= 1.6.1, < 3.0)
+ rubyzip (~> 1.1)
+ winrm
+
+GIT
+ remote: git://github.com/winrb/winrm.git
+ revision: 0f35bbd963024b32cc8e262f25e6110c6abf5794
+ branch: winrm-v2
+ specs:
+ winrm (2.0.0)
+ builder (>= 2.1.2)
+ erubis (~> 2.7)
+ gssapi (~> 1.2)
+ gyoku (~> 1.0)
+ httpclient (~> 2.2, >= 2.2.0.2)
+ logging (>= 1.6.1, < 3.0)
+ nori (~> 2.0)
+ rubyntlm (~> 0.6.0)
+
GEM
remote: https://rubygems.org/
specs:
addressable (2.4.0)
- artifactory (2.3.2)
- aws-sdk (2.3.14)
- aws-sdk-resources (= 2.3.14)
- aws-sdk-core (2.3.14)
+ artifactory (2.3.3)
+ aws-sdk (2.4.2)
+ aws-sdk-resources (= 2.4.2)
+ aws-sdk-core (2.4.2)
jmespath (~> 1.0)
- aws-sdk-resources (2.3.14)
- aws-sdk-core (= 2.3.14)
+ aws-sdk-resources (2.4.2)
+ aws-sdk-core (= 2.4.2)
berkshelf (4.3.5)
addressable (~> 2.3, >= 2.3.4)
berkshelf-api-client (~> 2.0, >= 2.0.2)
@@ -53,21 +124,21 @@ GEM
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.11.18)
+ chef-config (12.12.15)
fuzzyurl (~> 0.8.0)
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
cleanroom (1.0.0)
coderay (1.1.1)
diff-lcs (1.2.5)
- docker-api (1.28.0)
+ docker-api (1.29.1)
excon (>= 0.38.0)
json
erubis (2.7.0)
- excon (0.49.0)
+ excon (0.51.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.10)
+ ffi (1.9.14)
fuzzyurl (0.8.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
@@ -87,19 +158,14 @@ GEM
rubyzip (~> 1.1)
thor (~> 0.19)
train (~> 0.13)
- jmespath (1.2.4)
- json_pure (>= 1.8.1)
+ jmespath (1.3.1)
json (1.8.3)
- json_pure (1.8.3)
- kitchen-ec2 (1.0.0)
+ kitchen-ec2 (1.0.1)
aws-sdk (~> 2)
excon
multi_json
retryable (~> 2.0)
test-kitchen (~> 1.4, >= 1.4.1)
- kitchen-inspec (0.14.0)
- inspec (>= 0.22.0, < 1.0.0)
- test-kitchen (~> 1.6)
kitchen-vagrant (0.20.0)
test-kitchen (~> 1.4)
little-plugger (1.1.4)
@@ -108,11 +174,12 @@ GEM
multi_json (~> 1.10)
method_source (0.8.2)
minitar (0.5.4)
- mixlib-archive (0.1.0)
+ mixlib-archive (0.2.0)
+ mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
mixlib-config (2.2.1)
- mixlib-install (1.0.13)
+ mixlib-install (1.1.0)
artifactory
mixlib-shellout
mixlib-versioning
@@ -124,18 +191,18 @@ GEM
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (3.1.1)
+ net-ssh (3.2.0)
nio4r (1.2.1)
nori (2.6.0)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
- pry (0.10.3)
+ pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rainbow (2.1.0)
- retryable (2.0.3)
- ridley (4.5.1)
+ retryable (2.0.4)
+ ridley (4.6.0)
addressable
buff-config (~> 1.0)
buff-extensions (~> 1.0)
@@ -153,22 +220,22 @@ GEM
retryable (~> 2.0)
semverse (~> 1.1)
varia_model (~> 0.4.0)
- rspec (3.4.0)
- rspec-core (~> 3.4.0)
- rspec-expectations (~> 3.4.0)
- rspec-mocks (~> 3.4.0)
- rspec-core (3.4.4)
- rspec-support (~> 3.4.0)
- rspec-expectations (3.4.0)
+ rspec (3.5.0)
+ rspec-core (~> 3.5.0)
+ rspec-expectations (~> 3.5.0)
+ rspec-mocks (~> 3.5.0)
+ rspec-core (3.5.1)
+ rspec-support (~> 3.5.0)
+ rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
+ rspec-support (~> 3.5.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.4.1)
+ rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
- rspec-support (3.4.1)
+ rspec-support (~> 3.5.0)
+ rspec-support (3.5.0)
rubyntlm (0.6.0)
rubyzip (1.2.0)
safe_yaml (1.0.4)
@@ -180,42 +247,14 @@ GEM
solve (2.0.3)
molinillo (~> 0.4.2)
semverse (~> 1.1)
- test-kitchen (1.9.2)
- mixlib-install (~> 1.0, >= 1.0.4)
- mixlib-shellout (>= 1.2, < 3.0)
- net-scp (~> 1.1)
- net-ssh (>= 2.9, < 4.0)
- safe_yaml (~> 1.0)
- thor (~> 0.18)
thor (0.19.1)
timers (4.0.4)
hitimes
- train (0.13.1)
- docker-api (~> 1.26)
- json (~> 1.8)
- mixlib-shellout (~> 2.0)
- net-scp (~> 1.2)
- net-ssh (>= 2.9, < 4.0)
- winrm (~> 1.6)
- winrm-fs (~> 0.3)
varia_model (0.4.1)
buff-extensions (~> 1.0)
hashie (>= 2.0.2, < 4.0.0)
windows_chef_zero (2.0.0)
test-kitchen (>= 1.2.1)
- winrm (1.8.1)
- builder (>= 2.1.2)
- gssapi (~> 1.2)
- gyoku (~> 1.0)
- httpclient (~> 2.2, >= 2.2.0.2)
- logging (>= 1.6.1, < 3.0)
- nori (~> 2.0)
- rubyntlm (~> 0.6.0)
- winrm-fs (0.4.2)
- erubis (~> 2.7)
- logging (>= 1.6.1, < 3.0)
- rubyzip (~> 1.1)
- winrm (~> 1.5)
PLATFORMS
ruby
@@ -225,11 +264,14 @@ DEPENDENCIES
chef-acceptance!
inspec
kitchen-ec2
- kitchen-inspec
+ kitchen-inspec!
kitchen-vagrant
- test-kitchen
+ test-kitchen!
+ train!
windows_chef_zero
- winrm-fs
+ winrm!
+ winrm-elevated!
+ winrm-fs!
BUNDLED WITH
1.12.5
diff --git a/acceptance/data-collector/Berksfile.lock b/acceptance/data-collector/Berksfile.lock
deleted file mode 100644
index 39f4ce30dc..0000000000
--- a/acceptance/data-collector/Berksfile.lock
+++ /dev/null
@@ -1,6 +0,0 @@
-DEPENDENCIES
- data-collector-test
- path: .acceptance/data-collector-test
-
-GRAPH
- data-collector-test (0.1.0)
diff --git a/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb b/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
index be15b96429..f9d365ac58 100644
--- a/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
+++ b/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
@@ -110,6 +110,7 @@ shared_examples_for "run_converge.success payload check" do
expanded_run_list
message_type
message_version
+ node
node_name
organization_name
resources
@@ -150,6 +151,7 @@ shared_examples_for "run_converge.failure payload check" do
expanded_run_list
message_type
message_version
+ node
node_name
organization_name
resources
@@ -178,44 +180,6 @@ shared_examples_for "run_converge.failure payload check" do
end
end
-shared_examples_for "node-update payload check" do
- describe "node update message" do
- let(:required_fields) do
- %w{
- entity_name
- entity_type
- entity_uuid
- id
- message_type
- message_version
- organization_name
- recorded_at
- remote_hostname
- requestor_name
- requestor_type
- run_id
- service_hostname
- source
- task
- user_agent
- }
- end
- let(:optional_fields) { %{data} }
-
- it "is not missing any required fields" do
- payload = JSON.load(command("curl http://localhost:9292/cache/action").stdout)
- missing_fields = required_fields.select { |key| !payload.key?(key) }
- expect(missing_fields).to eq([])
- end
-
- it "does not have any extra fields" do
- payload = JSON.load(command("curl http://localhost:9292/cache/action").stdout)
- extra_fields = payload.keys.select { |key| !required_fields.include?(key) && !optional_fields.include?(key) }
- expect(extra_fields).to eq([])
- end
- end
-end
-
describe "CCR with no data collector URL configured" do
include_examples "successful chef run", "chef-client -z -c /etc/chef/no-endpoint.rb"
include_examples "counter checks", { "run_start" => nil, "run_converge.success" => nil, "run_converge.failure" => nil }
@@ -226,7 +190,6 @@ describe "CCR, local mode, config in solo mode" do
include_examples "counter checks", { "run_start" => 1, "run_converge.success" => 1, "run_converge.failure" => nil }
include_examples "run_start payload check"
include_examples "run_converge.success payload check"
- include_examples "node-update payload check"
end
describe "CCR, local mode, config in client mode" do
@@ -239,7 +202,6 @@ describe "CCR, local mode, config in both mode" do
include_examples "counter checks", { "run_start" => 1, "run_converge.success" => 1, "run_converge.failure" => nil }
include_examples "run_start payload check"
include_examples "run_converge.success payload check"
- include_examples "node-update payload check"
end
describe "CCR, local mode, config in solo mode, failed run" do
@@ -247,5 +209,4 @@ describe "CCR, local mode, config in solo mode, failed run" do
include_examples "counter checks", { "run_start" => 1, "run_converge.success" => nil, "run_converge.failure" => 1 }
include_examples "run_start payload check"
include_examples "run_converge.failure payload check"
- include_examples "node-update payload check"
end
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 203ea9809a..73f5151bca 100644
--- a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb
+++ b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb
@@ -3,6 +3,8 @@ class TopCookbooks < Chef::Resource
property :command, String, name_property: true
+ # Disabling all windows tests until winrm issue is properly settled.
+ #
action :run do
cookbook_kitchen "#{command} docker" do
end
@@ -33,8 +35,6 @@ class TopCookbooks < Chef::Resource
repository "adamedx/winbox"
end
- # Temporarily disabling windows and chocolatey to eliminate
- # transient errors on the builders
# cookbook_kitchen "#{command} windows" do
# end
diff --git a/acceptance/trivial/.kitchen.yml b/acceptance/trivial/.kitchen.yml
index 1e0af03503..0db67c468f 100644
--- a/acceptance/trivial/.kitchen.yml
+++ b/acceptance/trivial/.kitchen.yml
@@ -3,5 +3,5 @@ verifier:
suites:
- name: chef-current-install
- includes: [windows-2012r2]
+ includes: [ubuntu-14.04, windows-server-2012r2]
run_list:
diff --git a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/destroy.rb b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/destroy.rb
index e2d663ac2f..e12f938cf3 100644
--- a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/destroy.rb
+++ b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/destroy.rb
@@ -1 +1 @@
-kitchen "destroy"
+#kitchen "destroy"
diff --git a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/provision.rb b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/provision.rb
index 5726c0e7b5..cec9de4e5d 100644
--- a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/provision.rb
+++ b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/provision.rb
@@ -1 +1 @@
-kitchen "converge"
+#kitchen "converge"
diff --git a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/verify.rb b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/verify.rb
index 05ac94ce66..52e3560cf6 100644
--- a/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/verify.rb
+++ b/acceptance/windows-service/.acceptance/acceptance-cookbook/recipes/verify.rb
@@ -1 +1 @@
-kitchen "verify"
+#kitchen "verify"
diff --git a/acceptance/windows-service/test/integration/chef-windows-service/inspec/chef_windows_service_spec.rb b/acceptance/windows-service/test/integration/chef-windows-service/inspec/chef_windows_service_spec.rb
index a791177362..75383b69bf 100644
--- a/acceptance/windows-service/test/integration/chef-windows-service/inspec/chef_windows_service_spec.rb
+++ b/acceptance/windows-service/test/integration/chef-windows-service/inspec/chef_windows_service_spec.rb
@@ -13,7 +13,7 @@ describe service("chef-client") do
it { should_not be_running }
end
-describe command("chef-service-manager -a install") do
+describe command("/opscode/chef/bin/chef-service-manager.bat -a install") do
its("exit_status") { should eq 0 }
its(:stdout) { should match /Service 'chef-client' has successfully been installed./ }
end
@@ -24,7 +24,7 @@ describe service("chef-client") do
it { should_not be_running }
end
-describe command("chef-service-manager -a start") do
+describe command("/opscode/chef/bin/chef-service-manager.bat -a start") do
its("exit_status") { should eq 0 }
its(:stdout) { should match /Service 'chef-client' is now 'running'/ }
end
@@ -35,7 +35,7 @@ describe service("chef-client") do
it { should be_running }
end
-describe command("chef-service-manager -a stop") do
+describe command("/opscode/chef/bin/chef-service-manager.bat -a stop") do
its("exit_status") { should eq 0 }
its(:stdout) { should match /Service 'chef-client' is now 'stopped'/ }
end
@@ -46,7 +46,7 @@ describe service("chef-client") do
it { should_not be_running }
end
-describe command("chef-service-manager -a uninstall") do
+describe command("/opscode/chef/bin/chef-service-manager.bat -a uninstall") do
its("exit_status") { should eq 0 }
its(:stdout) { should match /Service chef-client deleted/ }
end
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index 094c8641a3..a194edc80e 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -132,8 +132,8 @@ module ChefConfig
until File.directory?(PathHelper.join(path, "cookbooks")) || File.directory?(PathHelper.join(path, "cookbook_artifacts"))
new_path = File.expand_path("..", path)
if new_path == path
- ChefConfig.logger.warn("No cookbooks directory found at or above current directory. Assuming #{Dir.pwd}.")
- return Dir.pwd
+ ChefConfig.logger.warn("No cookbooks directory found at or above current directory. Assuming #{cwd}.")
+ return cwd
end
path = new_path
end
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 2cc2ef8780..3387b5d49a 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 = "12.12.7"
+ VERSION = "12.13.16"
end
#
diff --git a/chef.gemspec b/chef.gemspec
index b88c899d5c..14b31ca23e 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -17,10 +17,11 @@ Gem::Specification.new do |s|
s.add_dependency "chef-config", "= #{Chef::VERSION}"
- s.add_dependency "mixlib-cli", "~> 1.4"
+ s.add_dependency "mixlib-cli", "~> 1.4", "< 1.7"
s.add_dependency "mixlib-log", "~> 1.3"
s.add_dependency "mixlib-authentication", "~> 1.4"
s.add_dependency "mixlib-shellout", "~> 2.0"
+ s.add_dependency "mixlib-archive", ">= 0.2.0"
s.add_dependency "ohai", ">= 8.6.0.alpha.1", "< 9"
s.add_dependency "ffi-yajl", "~> 2.2"
@@ -31,13 +32,13 @@ Gem::Specification.new do |s|
s.add_dependency "erubis", "~> 2.7"
s.add_dependency "diff-lcs", "~> 1.2", ">= 1.2.4"
- s.add_dependency "chef-zero", "~> 4.5"
+ s.add_dependency "chef-zero", "~> 4.8"
s.add_dependency "plist", "~> 3.2"
s.add_dependency "iniparse", "~> 1.4"
# Audit mode requires these, so they are non-developmental dependencies now
- %w{rspec-core rspec-expectations rspec-mocks}.each { |gem| s.add_dependency gem, "~> 3.4" }
+ %w{rspec-core rspec-expectations rspec-mocks}.each { |gem| s.add_dependency gem, "~> 3.5" }
s.add_dependency "rspec_junit_formatter", "~> 0.2.0"
s.add_dependency "serverspec", "~> 2.7"
s.add_dependency "specinfra", "~> 2.10"
diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml
index 99486928de..dd92b832dc 100644
--- a/kitchen-tests/.kitchen.travis.yml
+++ b/kitchen-tests/.kitchen.travis.yml
@@ -24,6 +24,7 @@ provisioner:
verifier:
name: inspec
+ format: progress
platforms:
- name: debian-7
diff --git a/kitchen-tests/.kitchen.yml b/kitchen-tests/.kitchen.yml
index c02ea55a02..314857663e 100644
--- a/kitchen-tests/.kitchen.yml
+++ b/kitchen-tests/.kitchen.yml
@@ -7,6 +7,7 @@ driver:
verifier:
name: inspec
+ format: progress
provisioner:
name: chef_github
diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock
index 79bb375d05..eeecf4954f 100644
--- a/kitchen-tests/Berksfile.lock
+++ b/kitchen-tests/Berksfile.lock
@@ -12,7 +12,7 @@ GRAPH
apache2 (3.2.2)
apt (4.0.1)
compat_resource (>= 12.10)
- aws (3.3.3)
+ aws (3.4.0)
ohai (>= 2.1.0)
base (0.1.0)
apt (>= 0.0.0)
@@ -50,7 +50,7 @@ GRAPH
mysql-chef_gem (~> 0.0)
postgresql (>= 1.0.0)
xfs (>= 0.0.0)
- iis (4.1.8)
+ iis (4.1.10)
windows (>= 1.34.6)
iptables (2.2.0)
logrotate (1.9.2)
@@ -98,7 +98,7 @@ GRAPH
database (~> 2.3.1)
mysql (~> 5.6.3)
php (~> 1.5.0)
- windows (1.44.0)
+ windows (1.44.1)
chef_handler (>= 0.0.0)
xfs (2.0.1)
xml (2.0.0)
diff --git a/kitchen-tests/Gemfile.lock b/kitchen-tests/Gemfile.lock
index 8ab7fbe707..edc91cc8b2 100644
--- a/kitchen-tests/Gemfile.lock
+++ b/kitchen-tests/Gemfile.lock
@@ -2,14 +2,14 @@ GEM
remote: https://rubygems.org/
specs:
addressable (2.4.0)
- artifactory (2.3.2)
- aws-sdk (2.3.9)
- aws-sdk-resources (= 2.3.9)
- aws-sdk-core (2.3.9)
+ artifactory (2.3.3)
+ aws-sdk (2.3.21)
+ aws-sdk-resources (= 2.3.21)
+ aws-sdk-core (2.3.21)
jmespath (~> 1.0)
- aws-sdk-resources (2.3.9)
- aws-sdk-core (= 2.3.9)
- berkshelf (4.3.3)
+ aws-sdk-resources (2.3.21)
+ aws-sdk-core (= 2.3.21)
+ berkshelf (4.3.5)
addressable (~> 2.3, >= 2.3.4)
berkshelf-api-client (~> 2.0, >= 2.0.2)
buff-config (~> 1.0)
@@ -21,6 +21,7 @@ GEM
faraday (~> 0.9)
httpclient (~> 2.7)
minitar (~> 0.5, >= 0.5.4)
+ mixlib-archive (~> 0.1)
octokit (~> 4.0)
retryable (~> 2.0)
ridley (~> 4.5)
@@ -44,21 +45,21 @@ GEM
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.10.24)
+ chef-config (12.12.15)
fuzzyurl (~> 0.8.0)
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
cleanroom (1.0.0)
coderay (1.1.1)
diff-lcs (1.2.5)
- docker-api (1.26.2)
+ docker-api (1.29.0)
excon (>= 0.38.0)
json
erubis (2.7.0)
- excon (0.49.0)
+ excon (0.51.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.10)
+ ffi (1.9.14)
fuzzyurl (0.8.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
@@ -66,26 +67,23 @@ GEM
builder (>= 2.1.2)
hashie (3.4.4)
hitimes (1.2.4)
- hitimes (1.2.4-x86-mingw32)
httpclient (2.7.2)
- inspec (0.22.1)
+ inspec (0.27.0)
hashie (~> 3.4)
json (~> 1.8)
method_source (~> 0.8)
pry (~> 0)
- r-train (~> 0.12)
rainbow (~> 2)
rspec (~> 3)
rspec-its (~> 1.2)
rubyzip (~> 1.1)
thor (~> 0.19)
- jmespath (1.2.4)
- json_pure (>= 1.8.1)
+ train (>= 0.15.1, < 1.0)
+ jmespath (1.3.0)
json (1.8.3)
- json_pure (1.8.3)
kitchen-appbundle-updater (0.1.2)
- kitchen-dokken (0.0.29)
- docker-api (~> 1.26.2)
+ kitchen-dokken (0.0.31)
+ docker-api (~> 1.29)
test-kitchen (~> 1.5)
kitchen-ec2 (1.0.0)
aws-sdk (~> 2)
@@ -104,44 +102,32 @@ GEM
multi_json (~> 1.10)
method_source (0.8.2)
minitar (0.5.4)
- mixlib-authentication (1.4.0)
+ mixlib-archive (0.2.0)
+ mixlib-log
+ mixlib-authentication (1.4.1)
mixlib-log
- rspec-core (~> 3.2)
- rspec-expectations (~> 3.2)
- rspec-mocks (~> 3.2)
mixlib-config (2.2.1)
- mixlib-install (1.0.12)
+ mixlib-install (1.1.0)
artifactory
mixlib-shellout
mixlib-versioning
mixlib-log (1.6.0)
mixlib-shellout (2.2.6)
- mixlib-shellout (2.2.6-universal-mingw32)
- win32-process (~> 0.8.2)
- wmi-lite (~> 1.0)
mixlib-versioning (1.1.0)
molinillo (0.4.5)
multi_json (1.12.1)
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (3.1.1)
+ net-ssh (3.2.0)
nio4r (1.2.1)
nori (2.6.0)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
- pry (0.10.3)
+ pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- r-train (0.12.1)
- docker-api (~> 1.26)
- json (~> 1.8)
- mixlib-shellout (~> 2.0)
- net-scp (~> 1.2)
- net-ssh (>= 2.9, < 4.0)
- winrm (~> 1.6)
- winrm-fs (~> 0.3)
rainbow (2.1.0)
retryable (2.0.3)
ridley (4.5.1)
@@ -162,22 +148,22 @@ GEM
retryable (~> 2.0)
semverse (~> 1.1)
varia_model (~> 0.4.0)
- rspec (3.4.0)
- rspec-core (~> 3.4.0)
- rspec-expectations (~> 3.4.0)
- rspec-mocks (~> 3.4.0)
- rspec-core (3.4.4)
- rspec-support (~> 3.4.0)
- rspec-expectations (3.4.0)
+ rspec (3.5.0)
+ rspec-core (~> 3.5.0)
+ rspec-expectations (~> 3.5.0)
+ rspec-mocks (~> 3.5.0)
+ rspec-core (3.5.1)
+ rspec-support (~> 3.5.0)
+ rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
+ rspec-support (~> 3.5.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.4.1)
+ rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.4.0)
- rspec-support (3.4.1)
+ rspec-support (~> 3.5.0)
+ rspec-support (3.5.0)
rubyntlm (0.6.0)
rubyzip (1.2.0)
safe_yaml (1.0.4)
@@ -189,7 +175,7 @@ GEM
solve (2.0.3)
molinillo (~> 0.4.2)
semverse (~> 1.1)
- test-kitchen (1.9.0)
+ test-kitchen (1.10.2)
mixlib-install (~> 1.0, >= 1.0.4)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
@@ -199,12 +185,18 @@ GEM
thor (0.19.1)
timers (4.0.4)
hitimes
+ train (0.15.1)
+ docker-api (~> 1.26)
+ json (~> 1.8)
+ mixlib-shellout (~> 2.0)
+ net-scp (~> 1.2)
+ net-ssh (>= 2.9, < 4.0)
+ winrm (~> 1.6)
+ winrm-fs (~> 0.3)
vagrant-wrapper (2.0.3)
varia_model (0.4.1)
buff-extensions (~> 1.0)
hashie (>= 2.0.2, < 4.0.0)
- win32-process (0.8.3)
- ffi (>= 1.0.0)
winrm (1.8.1)
builder (>= 2.1.2)
gssapi (~> 1.2)
@@ -213,16 +205,14 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0)
- winrm-fs (0.4.2)
+ winrm-fs (0.4.3)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
winrm (~> 1.5)
- wmi-lite (1.0.0)
PLATFORMS
ruby
- x86-mingw32
DEPENDENCIES
berkshelf
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index f8df71f723..6c2fc8b11b 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -28,6 +28,10 @@ require "mixlib/cli"
require "tmpdir"
require "rbconfig"
require "chef/application/exit_code"
+require "resolv"
+# on linux, we replace the glibc resolver with the ruby resolv library, which
+# supports reloading.
+require "resolv-replace" if RbConfig::CONFIG["host_os"] =~ /linux/
class Chef
class Application
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 77c86ad559..2a2f70c3a1 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -27,6 +27,7 @@ require "chef/handler/error_report"
require "chef/workstation_config_loader"
require "chef/mixin/shell_out"
require "chef-config/mixin/dot_d"
+require "mixlib/archive"
class Chef::Application::Client < Chef::Application
include Chef::Mixin::ShellOut
@@ -334,8 +335,7 @@ class Chef::Application::Client < Chef::Application
FileUtils.mkdir_p(Chef::Config.chef_repo_path)
tarball_path = File.join(Chef::Config.chef_repo_path, "recipes.tgz")
fetch_recipe_tarball(Chef::Config[:recipe_url], tarball_path)
- result = shell_out!("tar zxvf #{tarball_path} -C #{Chef::Config.chef_repo_path}")
- Chef::Log.debug "#{result.stdout}"
+ Mixlib::Archive.new(tarball_path).extract(Chef::Config.chef_repo_path, perms: false, ignore: /^\.$/)
end
end
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index d2516926c4..a7c4038f4c 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -29,6 +29,7 @@ require "fileutils"
require "chef/mixin/shell_out"
require "pathname"
require "chef-config/mixin/dot_d"
+require "mixlib/archive"
class Chef::Application::Solo < Chef::Application
include Chef::Mixin::ShellOut
@@ -273,8 +274,7 @@ class Chef::Application::Solo < Chef::Application
FileUtils.mkdir_p(recipes_path)
tarball_path = File.join(recipes_path, "recipes.tgz")
fetch_recipe_tarball(Chef::Config[:recipe_url], tarball_path)
- result = shell_out!("tar zxvf #{tarball_path} -C #{recipes_path}")
- Chef::Log.debug "#{result.stdout}"
+ Mixlib::Archive.new(tarball_path).extract(Chef::Config.chef_repo_path, perms: false, ignore: /^\.$/)
end
# json_attribs shuld be fetched after recipe_url tarball is unpacked.
diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb
index 100a72d2e1..837346381c 100644
--- a/lib/chef/audit/runner.rb
+++ b/lib/chef/audit/runner.rb
@@ -165,7 +165,7 @@ class Chef
add_example_group_methods
run_context.audits.each do |name, group|
ctl_grp = RSpec::Core::ExampleGroup.__control_group__(*group.args, &group.block)
- RSpec.world.register(ctl_grp)
+ RSpec.world.record(ctl_grp)
end
end
diff --git a/lib/chef/chef_fs/file_system/repository/directory.rb b/lib/chef/chef_fs/file_system/repository/directory.rb
index dae467993a..43f5719822 100644
--- a/lib/chef/chef_fs/file_system/repository/directory.rb
+++ b/lib/chef/chef_fs/file_system/repository/directory.rb
@@ -16,6 +16,8 @@
# limitations under the License.
#
+require "chef/chef_fs/file_system_cache"
+
class Chef
module ChefFS
module FileSystem
@@ -68,9 +70,11 @@ class Chef
end
def children
- dir_ls.sort.
+ return FileSystemCache.instance.children(file_path) if FileSystemCache.instance.exist?(file_path)
+ children = dir_ls.sort.
map { |child_name| make_child_entry(child_name) }.
select { |new_child| new_child.fs_entry_valid? && can_have_child?(new_child.name, new_child.dir?) }
+ FileSystemCache.instance.set_children(file_path, children)
rescue Errno::ENOENT => e
raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
end
diff --git a/lib/chef/chef_fs/file_system_cache.rb b/lib/chef/chef_fs/file_system_cache.rb
new file mode 100644
index 0000000000..38b4fda7ad
--- /dev/null
+++ b/lib/chef/chef_fs/file_system_cache.rb
@@ -0,0 +1,62 @@
+#
+# Copyright:: Copyright 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 "singleton"
+require "chef/client"
+
+class Chef
+ module ChefFS
+ class FileSystemCache
+ include Singleton
+
+ def initialize
+ @cache = {}
+
+ Chef::Client.when_run_starts do
+ FileSystemCache.instance.reset!
+ end
+ end
+
+ def reset!
+ @cache = {}
+ end
+
+ def exist?(path)
+ @cache.key?(path)
+ end
+
+ def children(path)
+ @cache[path]["children"]
+ end
+
+ def set_children(path, val)
+ @cache[path] ||= { "children" => [] }
+ @cache[path]["children"] = val
+ val
+ end
+
+ def fetch(path)
+ if @cache.key?(path)
+ @cache[path]
+ else
+ false
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb
index e7ef8d39ec..dbb0b3771a 100644
--- a/lib/chef/data_collector.rb
+++ b/lib/chef/data_collector.rb
@@ -57,6 +57,8 @@ class Chef
:current_resource_report, :enabled
def initialize
+ validate_data_collector_server_url!
+
@all_resource_reports = []
@current_resource_loaded = nil
@error_descriptions = {}
@@ -236,7 +238,8 @@ class Chef
yield
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
Errno::ECONNREFUSED, EOFError, Net::HTTPBadResponse,
- Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError => e
+ Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError,
+ Errno::EHOSTDOWN => e
disable_data_collector_reporter
code = if e.respond_to?(:response) && e.response.code
e.response.code.to_s
@@ -279,7 +282,6 @@ class Chef
# we have nothing to report.
return unless run_status
- send_to_data_collector(Chef::DataCollector::Messages.node_update_message(run_status).to_json)
send_to_data_collector(
Chef::DataCollector::Messages.run_end_message(
run_status: run_status,
@@ -377,6 +379,20 @@ class Chef
def nested_resource?(new_resource)
@current_resource_report && @current_resource_report.new_resource != new_resource
end
+
+ def validate_data_collector_server_url!
+ raise Chef::Exceptions::ConfigurationError,
+ "Chef::Config[:data_collector][:server_url] is empty. Please supply a valid URL." if data_collector_server_url.empty?
+
+ begin
+ uri = URI(data_collector_server_url)
+ rescue URI::InvalidURIError
+ raise Chef::Exceptions::ConfigurationError, "Chef::Config[:data_collector][:server_url] (#{data_collector_server_url}) is not a valid URI."
+ end
+
+ raise Chef::Exceptions::ConfigurationError,
+ "Chef::Config[:data_collector][:server_url] (#{data_collector_server_url}) is a URI with no host. Please supply a valid URL." if uri.host.nil?
+ end
end
end
end
diff --git a/lib/chef/data_collector/messages.rb b/lib/chef/data_collector/messages.rb
index 89bad9f9f9..8c2a84b580 100644
--- a/lib/chef/data_collector/messages.rb
+++ b/lib/chef/data_collector/messages.rb
@@ -68,6 +68,7 @@ class Chef
"id" => run_status.run_id,
"message_version" => "1.0.0",
"message_type" => "run_converge",
+ "node" => run_status.node,
"node_name" => run_status.node.name,
"organization_name" => organization,
"resources" => reporter_data[:resources].map(&:report_data),
@@ -90,36 +91,6 @@ class Chef
message
end
-
- #
- # Message payload that is sent to the DataCollector server at the
- # end of a Chef run.
- #
- # @param run_status [Chef::RunStatus] The RunStatus instance for this node/run.
- #
- # @return [Hash] A hash containing the node object and related metadata.
- #
- def self.node_update_message(run_status)
- {
- "entity_name" => run_status.node.name,
- "entity_type" => "node",
- "entity_uuid" => node_uuid,
- "id" => SecureRandom.uuid,
- "message_version" => "1.1.0",
- "message_type" => "action",
- "organization_name" => organization,
- "recorded_at" => Time.now.utc.iso8601,
- "remote_hostname" => run_status.node["fqdn"],
- "requestor_name" => run_status.node.name,
- "requestor_type" => "client",
- "run_id" => run_status.run_id,
- "service_hostname" => chef_server_fqdn(run_status),
- "source" => collector_source,
- "task" => "update",
- "user_agent" => Chef::HTTP::HTTPRequest::DEFAULT_UA,
- "data" => run_status.node,
- }
- end
end
end
end
diff --git a/lib/chef/data_collector/resource_report.rb b/lib/chef/data_collector/resource_report.rb
index 89b6d26706..dcaf9c8e44 100644
--- a/lib/chef/data_collector/resource_report.rb
+++ b/lib/chef/data_collector/resource_report.rb
@@ -65,20 +65,22 @@ class Chef
def to_hash
hash = {
- "type" => new_resource.resource_name.to_sym,
- "name" => new_resource.name.to_s,
- "id" => new_resource.identity.to_s,
- "after" => new_resource.state_for_resource_reporter,
- "before" => current_resource ? current_resource.state_for_resource_reporter : {},
- "duration" => elapsed_time_in_milliseconds.to_s,
- "delta" => new_resource.respond_to?(:diff) && potentially_changed? ? new_resource.diff : "",
- "result" => action.to_s,
- "status" => status,
+ "type" => new_resource.resource_name.to_sym,
+ "name" => new_resource.name.to_s,
+ "id" => new_resource.identity.to_s,
+ "after" => new_resource.state_for_resource_reporter,
+ "before" => current_resource ? current_resource.state_for_resource_reporter : {},
+ "duration" => elapsed_time_in_milliseconds.to_s,
+ "delta" => new_resource.respond_to?(:diff) && potentially_changed? ? new_resource.diff : "",
+ "ignore_failure" => new_resource.ignore_failure,
+ "result" => action.to_s,
+ "status" => status,
}
if new_resource.cookbook_name
hash["cookbook_name"] = new_resource.cookbook_name
hash["cookbook_version"] = new_resource.cookbook_version.version
+ hash["recipe_name"] = new_resource.recipe_name
end
hash["conditional"] = conditional.to_text if status == "skipped"
diff --git a/lib/chef/decorator/unchain.rb b/lib/chef/decorator/unchain.rb
new file mode 100644
index 0000000000..8093c70f4c
--- /dev/null
+++ b/lib/chef/decorator/unchain.rb
@@ -0,0 +1,59 @@
+class Chef
+ class Decorator < SimpleDelegator
+ #
+ # This decorator unchains method call chains and turns them into method calls
+ # with variable args. So this:
+ #
+ # node.set_unless["foo"]["bar"] = "baz"
+ #
+ # Can become:
+ #
+ # node.set_unless("foo", "bar", "baz")
+ #
+ # While this is a decorator it is not a Decorator and does not inherit because
+ # it deliberately does not need or want the method_missing magic. It is not legal
+ # to call anything on the intermediate values and only supports method chaining with
+ # #[] until the chain comes to an end with #[]=, so does not behave like a hash or
+ # array... e.g.
+ #
+ # node.default['foo'].keys is legal
+ # node.set_unless['foo'].keys is not legal now or ever
+ #
+ class Unchain
+ attr_accessor :__path__
+ attr_accessor :__method__
+
+ def initialize(obj, method)
+ @__path__ = []
+ @__method__ = method
+ @delegate_sd_obj = obj
+ end
+
+ def [](key)
+ __path__.push(key)
+ self
+ end
+
+ def []=(key, value)
+ __path__.push(key)
+ @delegate_sd_obj.public_send(__method__, *__path__, value)
+ end
+
+ # unfortunately we have to support method_missing for node.set_unless.foo.bar = 'baz' notation
+ def method_missing(symbol, *args)
+ if symbol == :to_ary
+ merged_attributes.send(symbol, *args)
+ elsif args.empty?
+ Chef.log_deprecation %q{method access to node attributes (node.foo.bar) is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]["bar"])}
+ self[symbol]
+ elsif symbol.to_s =~ /=$/
+ Chef.log_deprecation %q{method setting of node attributes (node.foo="bar") is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]="bar")}
+ key_to_set = symbol.to_s[/^(.+)=$/, 1]
+ self[key_to_set] = (args.length == 1 ? args[0] : args)
+ else
+ raise NoMethodError, "Undefined node attribute or method `#{symbol}' on `node'"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/dsl/cheffish.rb b/lib/chef/dsl/cheffish.rb
index de052bbe5c..03290b3674 100644
--- a/lib/chef/dsl/cheffish.rb
+++ b/lib/chef/dsl/cheffish.rb
@@ -27,6 +27,7 @@ class Chef
chef_acl
chef_client
chef_container
+ chef_data_bag_item
chef_data_bag
chef_environment
chef_group
diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb
index 8d76ddfb31..86227a0f9d 100644
--- a/lib/chef/dsl/declare_resource.rb
+++ b/lib/chef/dsl/declare_resource.rb
@@ -71,7 +71,15 @@ class Chef
# delete_resource!(:template, '/x/y.txy')
#
def delete_resource!(type, name, run_context: self.run_context)
- run_context.resource_collection.delete("#{type}[#{name}]")
+ run_context.resource_collection.delete("#{type}[#{name}]").tap do |resource|
+ # Purge any pending notifications too. This will not raise an exception
+ # if there are no notifications.
+ if resource
+ run_context.before_notification_collection.delete(resource.declared_key)
+ run_context.immediate_notification_collection.delete(resource.declared_key)
+ run_context.delayed_notification_collection.delete(resource.declared_key)
+ end
+ end
end
# Lookup a resource in the resource collection by name and delete it. Returns
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index ea90d80cd8..43759568a7 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -106,7 +106,12 @@ class Chef
# for back compat, need to raise an error that inherits from ArgumentError
class CookbookNotFoundInRepo < ArgumentError; end
class RecipeNotFound < ArgumentError; end
+ # AttributeNotFound really means the attribute file could not be found
class AttributeNotFound < RuntimeError; end
+ # NoSuchAttribute is raised on access by node.read!("foo", "bar") when node["foo"]["bar"] does not exist.
+ class NoSuchAttribute < RuntimeError; end
+ # AttributeTypeMismatch is raised by node.write!("foo", "bar", "baz") when e.g. node["foo"] = "bar" (overwriting String with Hash)
+ class AttributeTypeMismatch < RuntimeError; end
class MissingCookbookDependency < StandardError; end # CHEF-5120
class InvalidCommandOption < RuntimeError; end
class CommandTimeout < RuntimeError; end
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index c6afa97d23..3e69f58383 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -232,11 +232,11 @@ class Chef
# PERFORMANCE CRITICAL: *MUST* lazy require here otherwise we load up webrick
# via chef-zero and that hits DNS (at *require* time) which may timeout,
# when for most knife/chef-client work we never need/want this loaded.
- Thread.exclusive {
- unless defined?(SocketlessChefZeroClient)
- require "chef/http/socketless_chef_zero_client"
- end
- }
+
+ unless defined?(SocketlessChefZeroClient)
+ require "chef/http/socketless_chef_zero_client"
+ end
+
SocketlessChefZeroClient.new(base_url)
else
BasicClient.new(base_url, :ssl_policy => Chef::HTTP::APISSLPolicy)
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index f5dc29371f..18914f6be2 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -224,6 +224,7 @@ class Chef
unless valid_values.include?(v)
raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
end
+ v
}
option :node_verify_api_cert,
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
index 9a1ac93821..43d015dcc4 100644
--- a/lib/chef/knife/cookbook_site_install.rb
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -19,6 +19,7 @@
require "chef/knife"
require "chef/exceptions"
require "shellwords"
+require "mixlib/archive"
class Chef
class Knife
@@ -149,17 +150,7 @@ class Chef
def extract_cookbook(upstream_file, version)
ui.info("Uncompressing #{@cookbook_name} version #{version}.")
- extract_command = "tar zxvf \"#{convert_path upstream_file}\""
- if Chef::Platform.windows?
- tar_version = shell_out("tar --version").stdout.tr("\n", " ")
- if tar_version =~ /GNU tar/
- Chef::Log.debug("GNU tar detected, adding --force-local")
- extract_command << " --force-local"
- else
- Chef::Log.debug("non-GNU tar detected, not adding --force-local")
- end
- end
- shell_out!(extract_command, :cwd => @install_path)
+ Mixlib::Archive.new(convert_path(upstream_file)).extract(@install_path, perms: false)
end
def clear_existing_files(cookbook_path)
diff --git a/lib/chef/knife/cookbook_site_share.rb b/lib/chef/knife/cookbook_site_share.rb
index f500ba2182..d55d6c123a 100644
--- a/lib/chef/knife/cookbook_site_share.rb
+++ b/lib/chef/knife/cookbook_site_share.rb
@@ -113,19 +113,13 @@ class Chef
end
def get_category(cookbook_name)
- begin
- data = noauth_rest.get("https://supermarket.chef.io/api/v1/cookbooks/#{@name_args[0]}")
- if !data["category"] && data["error_code"]
- ui.fatal("Received an error from Supermarket: #{data["error_code"]}. On the first time you upload it, you are required to specify the category you want to share this cookbook to.")
- exit(1)
- else
- data["category"]
- end
- rescue => e
- ui.fatal("Unable to reach Supermarket: #{e.message}. Increase log verbosity (-VV) for more information.")
- Chef::Log.debug("\n#{e.backtrace.join("\n")}")
- exit(1)
- end
+ data = noauth_rest.get("#{config[:supermarket_site]}/api/v1/cookbooks/#{@name_args[0]}")
+ data["category"]
+ rescue => e
+ return "Other" if e.kind_of?(Net::HTTPServerException) && e.response.code == "404"
+ ui.fatal("Unable to reach Supermarket: #{e.message}. Increase log verbosity (-VV) for more information.")
+ Chef::Log.debug("\n#{e.backtrace.join("\n")}")
+ exit(1)
end
def do_upload(cookbook_filename, cookbook_category, user_id, user_secret_filename)
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 8d77becbf0..54faab6d3e 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -43,6 +43,8 @@ class Chef
def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
def_delegators :attributes, :rm, :rm_default, :rm_normal, :rm_override
def_delegators :attributes, :default!, :normal!, :override!, :force_default!, :force_override!
+ def_delegators :attributes, :default_unless, :normal_unless, :override_unless, :set_unless
+ def_delegators :attributes, :read, :read!, :write, :write!, :unlink, :unlink!
attr_accessor :recipe_list, :run_state, :override_runlist
@@ -196,35 +198,18 @@ class Chef
# might be missing
def normal
attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = false
attributes.normal
end
- alias_method :set, :normal
-
- # Set a normal attribute of this node, auto-vivifying any mashes that are
- # missing, but if the final value already exists, don't set it
- def normal_unless
- attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = true
- attributes.normal
+ def set
+ Chef.log_deprecation("node.set is deprecated and will be removed in Chef 14, please use node.default/node.override (or node.normal only if you really need persistence)")
+ normal
end
- alias_method :set_unless, :normal_unless
-
# Set a default of this node, but auto-vivify any Mashes that might
# be missing
def default
attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = false
- attributes.default
- end
-
- # Set a default attribute of this node, auto-vivifying any mashes that are
- # missing, but if the final value already exists, don't set it
- def default_unless
- attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = true
attributes.default
end
@@ -232,15 +217,6 @@ class Chef
# might be missing
def override
attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = false
- attributes.override
- end
-
- # Set an override attribute of this node, auto-vivifying any mashes that
- # are missing, but if the final value already exists, don't set it
- def override_unless
- attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = true
attributes.override
end
@@ -262,7 +238,6 @@ class Chef
def automatic_attrs
attributes.top_level_breadcrumb = nil
- attributes.set_unless_value_present = false
attributes.automatic
end
@@ -290,8 +265,14 @@ class Chef
end
# Only works for attribute fetches, setting is no longer supported
- def method_missing(symbol, *args)
- attributes.send(symbol, *args)
+ # XXX: this should be deprecated
+ def method_missing(method, *args, &block)
+ attributes.public_send(method, *args, &block)
+ end
+
+ # Fix respond_to + method so that it works with method_missing delegation
+ def respond_to_missing?(method, include_private = false)
+ attributes.respond_to?(method, false)
end
# Returns true if this Node expects a given recipe, false if not.
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index ab97cf99bf..f5fe89251d 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -19,6 +19,7 @@
require "chef/node/immutable_collections"
require "chef/node/attribute_collections"
+require "chef/decorator/unchain"
require "chef/mixin/deep_merge"
require "chef/log"
@@ -132,6 +133,7 @@ class Chef
:take,
:take_while,
:to_a,
+ :to_h,
:to_hash,
:to_set,
:value?,
@@ -187,8 +189,6 @@ class Chef
attr_accessor :deep_merge_cache
def initialize(normal, default, override, automatic)
- @set_unless_present = false
-
@default = VividMash.new(self, default)
@env_default = VividMash.new(self, {})
@role_default = VividMash.new(self, {})
@@ -214,15 +214,13 @@ class Chef
# attribute you're interested in. For example, to debug where the value
# of `node[:network][:default_interface]` is coming from, use:
# debug_value(:network, :default_interface).
- # The return value is an Array of Arrays. The first element is
- # `["set_unless_enabled?", Boolean]`, which describes whether the
- # attribute collection is in "set_unless" mode. The rest of the Arrays
+ # The return value is an Array of Arrays. The Arrays
# are pairs of `["precedence_level", value]`, where precedence level is
# the component, such as role default, normal, etc. and value is the
# attribute value set at that precedence level. If there is no value at
# that precedence level, +value+ will be the symbol +:not_present+.
def debug_value(*args)
- components = COMPONENTS.map do |component|
+ COMPONENTS.map do |component|
ivar = instance_variable_get(component)
value = args.inject(ivar) do |so_far, key|
if so_far == :not_present
@@ -235,12 +233,6 @@ class Chef
end
[component.to_s.sub(/^@/, ""), value]
end
- [["set_unless_enabled?", @set_unless_present]] + components
- end
-
- # Enables or disables `||=`-like attribute setting. See, e.g., Node#set_unless
- def set_unless_value_present=(setting)
- @set_unless_present = setting
end
# Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
@@ -321,94 +313,134 @@ class Chef
# clears attributes from all precedence levels
def rm(*args)
- reset(args[0])
- # just easier to compute our retval, rather than collect+merge sub-retvals
- ret = args.inject(merged_attributes) do |attr, arg|
- if attr.nil? || !attr.respond_to?(:[])
- nil
- else
- begin
- attr[arg]
- rescue TypeError
- raise TypeError, "Wrong type in index of attribute (did you use a Hash index on an Array?)"
- end
- end
+ with_deep_merged_return_value(self, *args) do
+ rm_default(*args)
+ rm_normal(*args)
+ rm_override(*args)
end
- rm_default(*args)
- rm_normal(*args)
- rm_override(*args)
- ret
end
- # does <level>['foo']['bar'].delete('baz')
- def remove_from_precedence_level(level, *args, key)
- multimash = level.element(*args)
- multimash.nil? ? nil : multimash.delete(key)
- end
-
- private :remove_from_precedence_level
-
# clears attributes from all default precedence levels
#
- # equivalent to: force_default!['foo']['bar'].delete('baz')
+ # similar to: force_default!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_default(*args)
- reset(args[0])
- remove_from_precedence_level(force_default!(autovivify: false), *args)
+ with_deep_merged_return_value(combined_default, *args) do
+ default.unlink(*args)
+ role_default.unlink(*args)
+ env_default.unlink(*args)
+ force_default.unlink(*args)
+ end
end
# clears attributes from normal precedence
#
# equivalent to: normal!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_normal(*args)
- reset(args[0])
- remove_from_precedence_level(normal!(autovivify: false), *args)
+ normal.unlink(*args)
end
# clears attributes from all override precedence levels
#
# equivalent to: force_override!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_override(*args)
- reset(args[0])
- remove_from_precedence_level(force_override!(autovivify: false), *args)
+ with_deep_merged_return_value(combined_override, *args) do
+ override.unlink(*args)
+ role_override.unlink(*args)
+ env_override.unlink(*args)
+ force_override.unlink(*args)
+ end
+ end
+
+ def with_deep_merged_return_value(obj, *path, last)
+ hash = obj.read(*path)
+ return nil unless hash.is_a?(Hash)
+ ret = hash[last]
+ yield
+ ret
end
+ private :with_deep_merged_return_value
+
#
# Replacing attributes without merging
#
# sets default attributes without merging
- def default!(opts = {})
- # FIXME: do not flush whole cache
- reset
- MultiMash.new(self, @default, [], opts)
+ #
+ # - this API autovivifies (and cannot trainwreck)
+ def default!(*args)
+ return Decorator::Unchain.new(self, :default!) unless args.length > 0
+ write(:default, *args)
end
# sets normal attributes without merging
- def normal!(opts = {})
- # FIXME: do not flush whole cache
- reset
- MultiMash.new(self, @normal, [], opts)
+ #
+ # - this API autovivifies (and cannot trainwreck)
+ def normal!(*args)
+ return Decorator::Unchain.new(self, :normal!) unless args.length > 0
+ write(:normal, *args)
end
# sets override attributes without merging
- def override!(opts = {})
- # FIXME: do not flush whole cache
- reset
- MultiMash.new(self, @override, [], opts)
+ #
+ # - this API autovivifies (and cannot trainwreck)
+ def override!(*args)
+ return Decorator::Unchain.new(self, :override!) unless args.length > 0
+ write(:override, *args)
end
# clears from all default precedence levels and then sets force_default
- def force_default!(opts = {})
- # FIXME: do not flush whole cache
- reset
- MultiMash.new(self, @force_default, [@default, @env_default, @role_default], opts)
+ #
+ # - this API autovivifies (and cannot trainwreck)
+ def force_default!(*args)
+ return Decorator::Unchain.new(self, :force_default!) unless args.length > 0
+ value = args.pop
+ rm_default(*args)
+ write(:force_default, *args, value)
end
# clears from all override precedence levels and then sets force_override
- def force_override!(opts = {})
- # FIXME: do not flush whole cache
- reset
- MultiMash.new(self, @force_override, [@override, @env_override, @role_override], opts)
+ def force_override!(*args)
+ return Decorator::Unchain.new(self, :force_override!) unless args.length > 0
+ value = args.pop
+ rm_override(*args)
+ write(:force_override, *args, value)
+ end
+
+ # method-style access to attributes
+
+ def read(*path)
+ merged_attributes.read(*path)
+ end
+
+ def read!(*path)
+ merged_attributes.read!(*path)
+ end
+
+ def exist?(*path)
+ merged_attributes.exist?(*path)
+ end
+
+ def write(level, *args, &block)
+ self.send(level).write(*args, &block)
+ end
+
+ def write!(level, *args, &block)
+ self.send(level).write!(*args, &block)
+ end
+
+ def unlink(level, *path)
+ self.send(level).unlink(*path)
+ end
+
+ def unlink!(level, *path)
+ self.send(level).unlink!(*path)
end
#
@@ -420,9 +452,9 @@ class Chef
#
def merged_attributes(*path)
- # immutablize(
+ # immutablize(
merge_all(path)
- # )
+ # )
end
def combined_override(*path)
@@ -433,6 +465,27 @@ class Chef
immutablize(merge_defaults(path))
end
+ def normal_unless(*args)
+ return Decorator::Unchain.new(self, :normal_unless) unless args.length > 0
+ write(:normal, *args) if read(*args[0...-1]).nil?
+ end
+
+ def default_unless(*args)
+ return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
+ write(:default, *args) if read(*args[0...-1]).nil?
+ end
+
+ def override_unless(*args)
+ return Decorator::Unchain.new(self, :override_unless) unless args.length > 0
+ write(:override, *args) if read(*args[0...-1]).nil?
+ end
+
+ def set_unless(*args)
+ Chef.log_deprecation("node.set_unless is deprecated and will be removed in Chef 14, please use node.default_unless/node.override_unless (or node.normal_unless if you really need persistence)")
+ return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
+ write(:normal, *args) if read(*args[0...-1]).nil?
+ end
+
def [](key)
if deep_merge_cache.has_key?(key.to_s)
# return the cache of the deep merged values by top-level key
@@ -461,13 +514,17 @@ class Chef
alias :each_attribute :each
def method_missing(symbol, *args)
- if args.empty?
+ if symbol == :to_ary
+ merged_attributes.send(symbol, *args)
+ elsif args.empty?
+ Chef.log_deprecation %q{method access to node attributes (node.foo.bar) is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]["bar"])}
if key?(symbol)
self[symbol]
else
raise NoMethodError, "Undefined method or attribute `#{symbol}' on `node'"
end
elsif symbol.to_s =~ /=$/
+ Chef.log_deprecation %q{method setting of node attributes (node.foo="bar") is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]="bar")}
key_to_set = symbol.to_s[/^(.+)=$/, 1]
self[key_to_set] = (args.length == 1 ? args[0] : args)
else
@@ -485,10 +542,6 @@ class Chef
}.join(", ") << ">"
end
- def set_unless?
- @set_unless_present
- end
-
private
# Helper method for merge_all/merge_defaults/merge_overrides.
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb
index 68f3a69756..b739ea8490 100644
--- a/lib/chef/node/attribute_collections.rb
+++ b/lib/chef/node/attribute_collections.rb
@@ -16,15 +16,15 @@
# limitations under the License.
#
+require "chef/node/common_api"
+
class Chef
class Node
-
# == AttrArray
# AttrArray is identical to Array, except that it keeps a reference to the
# "root" (Chef::Node::Attribute) object, and will trigger a cache
# invalidation on that object when mutated.
class AttrArray < Array
-
MUTATOR_METHODS = [
:<<,
:[]=,
@@ -62,8 +62,9 @@ class Chef
# Node::Attribute object.
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
+ ret = super(*args, &block)
root.reset_cache(root.top_level_breadcrumb)
- super(*args, &block)
+ ret
end
end
@@ -96,14 +97,12 @@ class Chef
# in the creation of a new VividMash for that key. (This only works when
# using the element reference method, `[]` -- other methods, such as
# #fetch, work as normal).
- # * It supports a set_unless flag (via the root Attribute object) which
- # allows `||=` style behavior (`||=` does not work with
- # auto-vivification). This is only implemented for #[]=; methods such as
- # #store work as normal.
# * attr_accessor style element set and get are supported via method_missing
class VividMash < Mash
attr_reader :root
+ include CommonAPI
+
# Methods that mutate a VividMash. Each of them is overridden so that it
# also invalidates the cached merged_attributes on the root Attribute
# object.
@@ -148,12 +147,9 @@ class Chef
def []=(key, value)
root.top_level_breadcrumb ||= key
- if set_unless? && key?(key) && !self[key].nil?
- self[key]
- else
- root.reset_cache(root.top_level_breadcrumb)
- super
- end
+ ret = super
+ root.reset_cache(root.top_level_breadcrumb)
+ ret
end
alias :attribute? :has_key?
@@ -176,10 +172,6 @@ class Chef
end
end
- def set_unless?
- @root.set_unless?
- end
-
def convert_key(key)
super
end
@@ -206,118 +198,5 @@ class Chef
end
end
-
- # == MultiMash
- # This is a Hash-like object that contains multiple VividMashes in it. Its
- # purpose is so that the user can descend into the mash and delete a subtree
- # from all of the Mash objects (used to delete all values in a subtree from
- # default, force_default, role_default and env_default at the same time). The
- # assignment operator strictly does assignment (does no merging) and works
- # by deleting the subtree and then assigning to the last mash which passed in
- # the initializer.
- #
- # A lot of the complexity of this class comes from the fact that at any key
- # value some or all of the mashes may walk off their ends and become nil or
- # true or something. The schema may change so that one precidence leve may
- # be 'true' object and another may be a VividMash. It is also possible that
- # one or many of them may transition from VividMashes to Hashes or Arrays.
- #
- # It also supports the case where you may be deleting a key using node.rm
- # in which case if intermediate keys all walk off into nil then you don't want
- # to be autovivifying keys as you go. On the other hand you may be using
- # node.force_default! in which case you'll wind up with a []= operator at the
- # end and you want autovivification, so we conditionally have to support either
- # operation.
- #
- # @todo: can we have an autovivify class that decorates a class that doesn't
- # autovivify or something so that the code is less awful?
- #
- class MultiMash
- attr_reader :root
- attr_reader :mashes
- attr_reader :opts
- attr_reader :primary_mash
-
- # Initialize with an array of mashes. For the delete return value to work
- # properly the mashes must come from the same attribute level (i.e. all
- # override or all default, but not a mix of both).
- def initialize(root, primary_mash, mashes, opts = {})
- @root = root
- @primary_mash = primary_mash
- @mashes = mashes
- @opts = opts
- @opts[:autovivify] = true if @opts[:autovivify].nil?
- end
-
- def [](key)
- # handle the secondary mashes
- new_mashes = []
- mashes.each do |mash|
- new_mash = safe_evalute_key(mash, key)
- # secondary mashes never autovivify so once they fall into nil, we just stop tracking them
- new_mashes.push(new_mash) unless new_mash.nil?
- end
-
- new_primary_mash = safe_evalute_key(primary_mash, key)
-
- if new_primary_mash.nil? && @opts[:autovivify]
- primary_mash[key] = VividMash.new(root)
- new_primary_mash = primary_mash[key]
- end
-
- MultiMash.new(root, new_primary_mash, new_mashes, opts)
- end
-
- def []=(key, value)
- if primary_mash.nil?
- # This theoretically should never happen since node#force_default! setter methods will autovivify and
- # node#rm methods do not end in #[]= operators.
- raise TypeError, "No autovivification was specified initially on a method chain ending in assignment"
- end
- ret = delete(key)
- primary_mash[key] = value
- ret
- end
-
- # mash.element('foo', 'bar') is the same as mash['foo']['bar']
- def element(key = nil, *subkeys)
- return self if key.nil?
- submash = self[key]
- subkeys.empty? ? submash : submash.element(*subkeys)
- end
-
- def delete(key)
- # the return value is a deep merge which is correct semantics when
- # merging between attributes on the same level (this would be incorrect
- # if passed both override and default attributes which would need hash_only
- # merging).
- ret = mashes.inject(Mash.new) do |merged, mash|
- Chef::Mixin::DeepMerge.merge(merged, mash)
- end
- ret = Chef::Mixin::DeepMerge.merge(ret, primary_mash)
- mashes.each do |mash|
- mash.delete(key) if mash.respond_to?(:delete)
- end
- primary_mash.delete(key) if primary_mash.respond_to?(:delete)
- ret[key]
- end
-
- private
-
- def safe_evalute_key(mash, key)
- if mash.respond_to?(:[])
- if mash.respond_to?(:has_key?)
- if mash.has_key?(key)
- return mash[key] if mash[key].respond_to?(:[])
- end
- elsif !mash[key].nil?
- return mash[key] if mash[key].respond_to?(:[])
- end
- end
- return nil
- end
-
- end
-
end
end
diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb
new file mode 100644
index 0000000000..ce2c6b6878
--- /dev/null
+++ b/lib/chef/node/common_api.rb
@@ -0,0 +1,129 @@
+#--
+# Copyright:: Copyright 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
+ class Node
+ # shared API between VividMash and ImmutableMash, writer code can be
+ # 'shared' to keep it logically in this file by adding them to the
+ # block list in ImmutableMash.
+ module CommonAPI
+ # method-style access to attributes
+
+ def valid_container?(obj, key)
+ return obj.is_a?(Hash) || (obj.is_a?(Array) && key.is_a?(Fixnum))
+ end
+
+ private :valid_container?
+
+ # - autovivifying / autoreplacing writer
+ # - non-container-ey intermediate objects are replaced with hashes
+ def write(*args, &block)
+ root.top_level_breadcrumb = nil if respond_to?(:root)
+ value = block_given? ? yield : args.pop
+ last = args.pop
+ prev_memo = prev_key = nil
+ chain = args.inject(self) do |memo, key|
+ if !valid_container?(memo, key)
+ prev_memo[prev_key] = {}
+ memo = prev_memo[prev_key]
+ end
+ prev_memo = memo
+ prev_key = key
+ memo[key]
+ end
+ if !valid_container?(chain, last)
+ prev_memo[prev_key] = {}
+ chain = prev_memo[prev_key]
+ end
+ chain[last] = value
+ end
+
+ # this autovivifies, but can throw NoSuchAttribute when trying to access #[] on
+ # something that is not a container ("schema violation" issues).
+ #
+ def write!(*args, &block)
+ root.top_level_breadcrumb = nil if respond_to?(:root)
+ value = block_given? ? yield : args.pop
+ last = args.pop
+ obj = args.inject(self) do |memo, key|
+ raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(memo, key)
+ memo[key]
+ end
+ raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(obj, last)
+ obj[last] = value
+ end
+
+ # FIXME:(?) does anyone need a non-autovivifying writer for attributes that throws exceptions?
+
+ # return true or false based on if the attribute exists
+ def exist?(*path)
+ root.top_level_breadcrumb = nil if respond_to?(:root)
+ path.inject(self) do |memo, key|
+ return false unless valid_container?(memo, key)
+ if memo.is_a?(Hash)
+ if memo.key?(key)
+ memo[key]
+ else
+ return false
+ end
+ elsif memo.is_a?(Array)
+ if memo.length > key
+ memo[key]
+ else
+ return false
+ end
+ end
+ end
+ return true
+ end
+
+ # this is a safe non-autovivifying reader that returns nil if the attribute does not exist
+ def read(*path)
+ begin
+ read!(*path)
+ rescue Chef::Exceptions::NoSuchAttribute
+ nil
+ end
+ end
+
+ # non-autovivifying reader that throws an exception if the attribute does not exist
+ def read!(*path)
+ raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
+ root.top_level_breadcrumb = nil if respond_to?(:root)
+ path.inject(self) do |memo, key|
+ memo[key]
+ end
+ end
+
+ # FIXME:(?) does anyone really like the autovivifying reader that we have and wants the same behavior? readers that write? ugh...
+
+ def unlink(*path, last)
+ root.top_level_breadcrumb = nil if respond_to?(:root)
+ hash = path.empty? ? self : read(*path)
+ return nil unless hash.is_a?(Hash) || hash.is_a?(Array)
+ root.top_level_breadcrumb ||= last
+ hash.delete(last)
+ end
+
+ def unlink!(*path)
+ raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
+ unlink(*path)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index b5fd86fa72..d4623ace2a 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -1,3 +1,21 @@
+#--
+# Copyright:: Copyright 2012-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 "chef/node/common_api"
class Chef
class Node
@@ -124,6 +142,7 @@ class Chef
class ImmutableMash < Mash
include Immutablize
+ include CommonAPI
alias :internal_set :[]=
private :internal_set
@@ -144,6 +163,10 @@ class Chef
:replace,
:select!,
:shift,
+ :write,
+ :write!,
+ :unlink,
+ :unlink!,
]
def initialize(mash_data)
@@ -167,13 +190,15 @@ class Chef
end
def method_missing(symbol, *args)
- if args.empty?
+ if symbol == :to_ary
+ super
+ elsif args.empty?
if key?(symbol)
self[symbol]
else
raise NoMethodError, "Undefined method or attribute `#{symbol}' on `node'"
end
- # This will raise a ImmutableAttributeModification error:
+ # This will raise a ImmutableAttributeModification error:
elsif symbol.to_s =~ /=$/
key_to_set = symbol.to_s[/^(.+)=$/, 1]
self[key_to_set] = (args.length == 1 ? args[0] : args)
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index 45ab4dd522..0589cb4c54 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -531,8 +531,6 @@ class Chef
end
end
- protected
-
#
# The options this Property will use for get/set behavior and validation.
#
@@ -583,6 +581,7 @@ class Chef
(options.has_key?(:is) && resource.send(:_pv_is, { name => nil }, name, options[:is], raise_error: false))
end
+ # @api private
def get_value(resource)
if instance_variable_name
resource.instance_variable_get(instance_variable_name)
@@ -591,6 +590,7 @@ class Chef
end
end
+ # @api private
def set_value(resource, value)
if instance_variable_name
resource.instance_variable_set(instance_variable_name, value)
@@ -599,6 +599,7 @@ class Chef
end
end
+ # @api private
def value_is_set?(resource)
if instance_variable_name
resource.instance_variable_defined?(instance_variable_name)
@@ -607,6 +608,7 @@ class Chef
end
end
+ # @api private
def reset_value(resource)
if instance_variable_name
if value_is_set?(resource)
@@ -617,6 +619,8 @@ class Chef
end
end
+ private
+
def exec_in_resource(resource, proc, *args)
if resource
if proc.arity > args.size
diff --git a/lib/chef/provider/batch.rb b/lib/chef/provider/batch.rb
index bb294afd3f..0d857aaa79 100644
--- a/lib/chef/provider/batch.rb
+++ b/lib/chef/provider/batch.rb
@@ -29,7 +29,7 @@ class Chef
end
def command
- basepath = is_forced_32bit ? wow64_directory : run_context.node.kernel.os_info.system_directory
+ basepath = is_forced_32bit ? wow64_directory : run_context.node["kernel"]["os_info"]["system_directory"]
interpreter_path = Chef::Util::PathHelper.join(basepath, interpreter)
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index 7f85085eeb..bb0762ceb7 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -154,6 +154,7 @@ class Chef
do_contents_changes
do_acl_changes
do_selinux
+ do_resolv_conf_fixup
load_resource_attributes_from_file(@new_resource)
end
@@ -445,6 +446,13 @@ class Chef
end
end
+ def do_resolv_conf_fixup
+ # reload /etc/resolv.conf after we edit it -- only on linux -- and see lib/chef/application.rb
+ if new_resource.path == "/etc/resolv.conf" && RbConfig::CONFIG["host_os"] =~ /linux/
+ Resolv::DefaultResolver.replace_resolvers [Resolv::DNS.new("/etc/resolv.conf")]
+ end
+ end
+
def do_acl_changes
if access_controls.requires_changes?
converge_by(access_controls.describe_changes) do
diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb
index a1709c4af7..728f181055 100644
--- a/lib/chef/provider/package/aix.rb
+++ b/lib/chef/provider/package/aix.rb
@@ -55,7 +55,11 @@ class Chef
ret = shell_out_with_timeout("installp -L -d #{@new_resource.source}")
ret.stdout.each_line do |line|
case line
- when /#{@new_resource.package_name}:/
+ when /:#{@new_resource.package_name}:/
+ fields = line.split(":")
+ @new_resource.version(fields[2])
+ when /^#{@new_resource.package_name}:/
+ Chef::Log.warn("You are installing a bff package by product name. For idempotent installs, please install individual filesets")
fields = line.split(":")
@new_resource.version(fields[2])
end
diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb
index 2120b9aa48..8043c01693 100644
--- a/lib/chef/provider/package/openbsd.rb
+++ b/lib/chef/provider/package/openbsd.rb
@@ -127,7 +127,7 @@ class Chef
end
def pkg_path
- ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node.kernel.name}/#{node.kernel.release}/packages/#{node.kernel.machine}/"
+ ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node["kernel"]["name"]}/#{node["kernel"]["release"]}/packages/#{node["kernel"]["machine"]}/"
end
end
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index 5ee1dbea8e..e20a7332f7 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -38,15 +38,15 @@ class Chef
status = shell_out_with_timeout!("zypper --non-interactive info #{package_name}")
status.stdout.each_line do |line|
case line
- when /^Version: (.+)$/
- candidate_version = $1
- Chef::Log.debug("#{new_resource} version #{$1}")
- when /^Installed: Yes$/
+ when /^Version *: (.+) *$/
+ candidate_version = $1.strip
+ Chef::Log.debug("#{new_resource} version #{candidate_version}")
+ when /^Installed *: Yes *$/
is_installed = true
Chef::Log.debug("#{new_resource} is installed")
- when /^Status: out-of-date \(version (.+) installed\)$/
- current_version = $1
- Chef::Log.debug("#{new_resource} out of date version #{$1}")
+ when /^Status *: out-of-date \(version (.+) installed\) *$/
+ current_version = $1.strip
+ Chef::Log.debug("#{new_resource} out of date version #{current_version}")
end
end
current_version = candidate_version if is_installed
diff --git a/lib/chef/provider/powershell_script.rb b/lib/chef/provider/powershell_script.rb
index 6365f6a171..ab85ec35ac 100644
--- a/lib/chef/provider/powershell_script.rb
+++ b/lib/chef/provider/powershell_script.rb
@@ -36,7 +36,7 @@ class Chef
end
def command
- basepath = is_forced_32bit ? wow64_directory : run_context.node.kernel.os_info.system_directory
+ basepath = is_forced_32bit ? wow64_directory : run_context.node["kernel"]["os_info"]["system_directory"]
# Powershell.exe is always in "v1.0" folder (for backwards compatibility)
interpreter_path = Chef::Util::PathHelper.join(basepath, "WindowsPowerShell", "v1.0", interpreter)
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 262aa84781..479eb0a7e2 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -260,6 +260,18 @@ class Chef
end
#
+ # Token class to hold an unresolved subscribes call with an associated
+ # run context.
+ #
+ # @api private
+ # @see Resource#subscribes
+ class UnresolvedSubscribes < self
+ # The full key ise given as the name in {Resource#subscribes}
+ alias_method :to_s, :name
+ alias_method :declared_key, :name
+ end
+
+ #
# Subscribes to updates from other resources, causing a particular action to
# run on *this* resource when the other resource is updated.
#
@@ -326,7 +338,7 @@ class Chef
resources = [resources].flatten
resources.each do |resource|
if resource.is_a?(String)
- resource = Chef::Resource.new(resource, run_context)
+ resource = UnresolvedSubscribes.new(resource, run_context)
end
if resource.run_context.nil?
resource.run_context = run_context
diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb
index d1f5c2e022..1641fe60f2 100644
--- a/lib/chef/resource_builder.rb
+++ b/lib/chef/resource_builder.rb
@@ -104,7 +104,11 @@ class Chef
end
def is_trivial_resource?(resource)
- identicalish_resources?(resource_class.new(name, run_context), resource)
+ trivial_resource = resource_class.new(name, run_context)
+ # force un-lazy the name property on the created trivial resource
+ name_property = resource_class.properties.find { |sym, p| p.name_property? }
+ trivial_resource.send(name_property[0]) unless name_property.nil?
+ identicalish_resources?(trivial_resource, resource)
end
# this is an equality test specific to checking for 3694 cloning warnings
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 29c936a932..7ef476c44b 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -194,12 +194,10 @@ class Chef
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_before(notification)
- nr = notification.notifying_resource
- if nr.instance_of?(Chef::Resource)
- before_notification_collection[nr.name] << notification
- else
- before_notification_collection[nr.declared_key] << notification
- end
+ # Note for the future, notification.notifying_resource may be an instance
+ # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
+ # with a string value.
+ before_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
@@ -208,12 +206,10 @@ class Chef
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_immediately(notification)
- nr = notification.notifying_resource
- if nr.instance_of?(Chef::Resource)
- immediate_notification_collection[nr.name] << notification
- else
- immediate_notification_collection[nr.declared_key] << notification
- end
+ # Note for the future, notification.notifying_resource may be an instance
+ # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
+ # with a string value.
+ immediate_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
@@ -222,12 +218,10 @@ class Chef
# @param [Chef::Resource::Notification] The notification to add.
#
def notifies_delayed(notification)
- nr = notification.notifying_resource
- if nr.instance_of?(Chef::Resource)
- delayed_notification_collection[nr.name] << notification
- else
- delayed_notification_collection[nr.declared_key] << notification
- end
+ # Note for the future, notification.notifying_resource may be an instance
+ # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
+ # with a string value.
+ delayed_notification_collection[notification.notifying_resource.declared_key] << notification
end
#
@@ -245,50 +239,29 @@ class Chef
#
# Get the list of before notifications sent by the given resource.
#
- # TODO seriously, this is actually wrong. resource.name is not unique,
- # you need the type as well.
- #
# @return [Array[Notification]]
#
def before_notifications(resource)
- if resource.instance_of?(Chef::Resource)
- return before_notification_collection[resource.name]
- else
- return before_notification_collection[resource.declared_key]
- end
+ return before_notification_collection[resource.declared_key]
end
#
# Get the list of immediate notifications sent by the given resource.
#
- # TODO seriously, this is actually wrong. resource.name is not unique,
- # you need the type as well.
- #
# @return [Array[Notification]]
#
def immediate_notifications(resource)
- if resource.instance_of?(Chef::Resource)
- return immediate_notification_collection[resource.name]
- else
- return immediate_notification_collection[resource.declared_key]
- end
+ return immediate_notification_collection[resource.declared_key]
end
#
# Get the list of delayed (end of run) notifications sent by the given
# resource.
#
- # TODO seriously, this is actually wrong. resource.name is not unique,
- # you need the type as well.
- #
# @return [Array[Notification]]
#
def delayed_notifications(resource)
- if resource.instance_of?(Chef::Resource)
- return delayed_notification_collection[resource.name]
- else
- return delayed_notification_collection[resource.declared_key]
- end
+ return delayed_notification_collection[resource.declared_key]
end
#
diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb
index aad5c49d00..26683cc25d 100644
--- a/lib/chef/shell.rb
+++ b/lib/chef/shell.rb
@@ -148,7 +148,7 @@ module Shell
end
def self.greeting
- " #{Etc.getlogin}@#{Shell.session.node.fqdn}"
+ " #{Etc.getlogin}@#{Shell.session.node["fqdn"]}"
rescue NameError, ArgumentError
""
end
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index 4bd8dc1c51..dbf514e6ca 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "12.12.7"
+ VERSION = "12.13.16"
end
#
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index 39f5dbba9d..f8cfeec014 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -1,13 +1,13 @@
GIT
remote: https://github.com/chef/omnibus-software.git
- revision: cb6f0afa1cd334f25aece7deeef3a9454cecc0e7
+ revision: 5e767a6d220f024256439b0a8415eefe923967dc
specs:
omnibus-software (4.0.0)
omnibus (>= 5.2.0)
GIT
remote: https://github.com/chef/omnibus.git
- revision: 56b8e507df41bc6fa6e452441dc9df5744892e34
+ revision: 29d390ec93709ceec2667038aed6769ee29a0646
specs:
omnibus (5.4.0)
aws-sdk (~> 2)
@@ -38,12 +38,12 @@ GEM
addressable (2.4.0)
artifactory (2.3.2)
awesome_print (1.7.0)
- aws-sdk (2.3.14)
- aws-sdk-resources (= 2.3.14)
- aws-sdk-core (2.3.14)
+ aws-sdk (2.4.2)
+ aws-sdk-resources (= 2.4.2)
+ aws-sdk-core (2.4.2)
jmespath (~> 1.0)
- aws-sdk-resources (2.3.14)
- aws-sdk-core (= 2.3.14)
+ aws-sdk-resources (2.4.2)
+ aws-sdk-core (= 2.4.2)
berkshelf (4.3.3)
addressable (~> 2.3, >= 2.3.4)
berkshelf-api-client (~> 2.0, >= 2.0.2)
@@ -82,20 +82,20 @@ GEM
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.11.18)
+ chef-config (12.12.15)
fuzzyurl (~> 0.8.0)
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
- chef-sugar (3.3.0)
+ chef-sugar (3.4.0)
cleanroom (1.0.0)
coderay (1.1.1)
debug_inspector (0.0.2)
erubis (2.7.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.10)
- ffi (1.9.10-x86-mingw32)
- ffi-yajl (2.2.3)
+ ffi (1.9.14)
+ ffi (1.9.14-x86-mingw32)
+ ffi-yajl (2.3.0)
libyajl2 (~> 1.2)
fuzzyurl (0.8.0)
gssapi (1.2.0)
@@ -108,10 +108,8 @@ GEM
httpclient (2.7.2)
iostruct (0.0.4)
ipaddress (0.8.3)
- jmespath (1.2.4)
- json_pure (>= 1.8.1)
+ jmespath (1.3.1)
json (1.8.3)
- json_pure (1.8.3)
kitchen-vagrant (0.19.0)
test-kitchen (~> 1.4)
libyajl2 (1.2.0)
@@ -145,7 +143,7 @@ GEM
nori (2.6.0)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
- ohai (8.17.0)
+ ohai (8.17.1)
chef-config (>= 12.5.0.alpha.1, < 13)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
diff --git a/pkg.rb b/pkg.rb
deleted file mode 100644
index bb26f257d0..0000000000
--- a/pkg.rb
+++ /dev/null
@@ -1 +0,0 @@
-package "chef-12.9.38-1.powerpc"
diff --git a/rubygems-pkg/rubygems-update-2.4.6.gem b/rubygems-pkg/rubygems-update-2.4.6.gem
deleted file mode 100644
index 97ebec693a..0000000000
--- a/rubygems-pkg/rubygems-update-2.4.6.gem
+++ /dev/null
Binary files differ
diff --git a/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb b/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb
index ef0967a4d2..e45e7d9f68 100644
--- a/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb
@@ -1,4 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "circular-dep1::default"
-
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "circular-dep1::default"
diff --git a/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb b/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb
index f2ef012aa1..37f396b1f9 100644
--- a/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "circular-dep2::default"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "circular-dep2::default"
diff --git a/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb b/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb
index e818d36a9e..3059494198 100644
--- a/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb
+++ b/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb
@@ -1,2 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "dependency1::aa_first"
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "dependency1::aa_first"
diff --git a/spec/data/run_context/cookbooks/dependency1/attributes/default.rb b/spec/data/run_context/cookbooks/dependency1/attributes/default.rb
index 6875274e3f..a65a3345bc 100644
--- a/spec/data/run_context/cookbooks/dependency1/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/dependency1/attributes/default.rb
@@ -1,2 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "dependency1::default"
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "dependency1::default"
diff --git a/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb b/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb
index 1a513b03d4..94ffb30133 100644
--- a/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb
+++ b/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "dependency1::zz_last"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "dependency1::zz_last"
diff --git a/spec/data/run_context/cookbooks/dependency2/attributes/default.rb b/spec/data/run_context/cookbooks/dependency2/attributes/default.rb
index 526751f422..8917bf9730 100644
--- a/spec/data/run_context/cookbooks/dependency2/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/dependency2/attributes/default.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "dependency2::default"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "dependency2::default"
diff --git a/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb b/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb
index 3ad2b925aa..07294665b2 100644
--- a/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb
+++ b/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "no-default-attr::server"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "no-default-attr::server"
diff --git a/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb b/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb
index cca56bc61f..77309462b1 100644
--- a/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "test-with-circular-deps::default"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "test-with-circular-deps::default"
diff --git a/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb b/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb
index 4d71cc3cfe..c4cc8151a4 100644
--- a/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb
+++ b/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb
@@ -1,3 +1,2 @@
-set_unless[:attr_load_order] = []
-set[:attr_load_order] << "test-with-deps::default"
-
+normal_unless[:attr_load_order] = []
+normal[:attr_load_order] << "test-with-deps::default"
diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/package_spec.rb
index 6dc55f7f01..0f01a751ec 100644
--- a/spec/functional/resource/package_spec.rb
+++ b/spec/functional/resource/package_spec.rb
@@ -260,7 +260,7 @@ describe Chef::Resource::Package, metadata do
end
before do
- node.set[:preseed_value] = "FROM TEMPLATE"
+ node.normal[:preseed_value] = "FROM TEMPLATE"
end
it "preseeds the package, then installs it" do
diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb
index f270043f2c..32529fbb0c 100644
--- a/spec/functional/resource/template_spec.rb
+++ b/spec/functional/resource/template_spec.rb
@@ -110,7 +110,7 @@ describe Chef::Resource::Template do
context "using single helper syntax referencing @node" do
before do
- node.set[:helper_test_attr] = "value from helper method"
+ node.normal[:helper_test_attr] = "value from helper method"
resource.helper(:helper_method) { "#{@node[:helper_test_attr]}" }
end
@@ -131,7 +131,7 @@ describe Chef::Resource::Template do
context "using an inline block referencing @node" do
before do
- node.set[:helper_test_attr] = "value from helper method"
+ node.normal[:helper_test_attr] = "value from helper method"
resource.helpers do
def helper_method
@@ -168,7 +168,7 @@ describe Chef::Resource::Template do
end
before do
- node.set[:helper_test_attr] = "value from helper method"
+ node.normal[:helper_test_attr] = "value from helper method"
resource.helpers(ExampleModuleReferencingATNode)
end
diff --git a/spec/functional/shell_spec.rb b/spec/functional/shell_spec.rb
index fe2abdb12a..636162fb16 100644
--- a/spec/functional/shell_spec.rb
+++ b/spec/functional/shell_spec.rb
@@ -137,7 +137,7 @@ describe Shell do
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}"]
+ show_recipes_code = %q[puts "#{node["recipes"].inspect}"]
keyboard.puts(show_recipes_code)
read_until(out, show_recipes_code)
end
diff --git a/spec/integration/knife/diff_spec.rb b/spec/integration/knife/diff_spec.rb
index b7d2f4d1c3..b3bd23f48e 100644
--- a/spec/integration/knife/diff_spec.rb
+++ b/spec/integration/knife/diff_spec.rb
@@ -72,7 +72,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
@@ -366,7 +366,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
diff --git a/spec/integration/knife/download_spec.rb b/spec/integration/knife/download_spec.rb
index a924226ea2..be0fc9d708 100644
--- a/spec/integration/knife/download_spec.rb
+++ b/spec/integration/knife/download_spec.rb
@@ -76,7 +76,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
@@ -645,7 +645,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
@@ -1271,7 +1271,7 @@ EOM
file "groups/x.json", {}
file "invitations.json", [ "foo" ]
file "members.json", [ "bar" ]
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "org.json", { "full_name" => "Something" }
file "policies/x-1.0.0.json", {}
file "policies/blah-1.0.0.json", {}
@@ -1295,7 +1295,7 @@ EOM
file "environments/x.json", { "description" => "foo" }
file "groups/x.json", { "description" => "foo" }
file "groups/x.json", { "groups" => [ "admin" ] }
- file "nodes/x.json", { "run_list" => [ "blah" ] }
+ file "nodes/x.json", { "normal" => { "tags" => [] }, "run_list" => [ "blah" ] }
file "org.json", { "full_name" => "Something Else " }
file "policies/x-1.0.0.json", { "run_list" => [ "blah" ] }
file "policy_groups/x.json", {
diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb
index 9078bf09a1..5e0d3a3d11 100644
--- a/spec/integration/knife/raw_spec.rb
+++ b/spec/integration/knife/raw_spec.rb
@@ -49,7 +49,9 @@ describe "knife raw", :workstation do
},
"normal": {
+ "tags": [
+ ]
},
"default": {
diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb
index 55c95b59b7..1db0ea8726 100644
--- a/spec/integration/knife/upload_spec.rb
+++ b/spec/integration/knife/upload_spec.rb
@@ -96,7 +96,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
@@ -802,7 +802,7 @@ EOM
file "data_bags/x/y.json", {}
file "environments/_default.json", { "description" => "The default Chef environment" }
file "environments/x.json", {}
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "roles/x.json", {}
file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
@@ -1313,7 +1313,7 @@ EOM
file "invitations.json", [ "foo" ]
file "members.json", [ "bar" ]
file "org.json", { "full_name" => "wootles" }
- file "nodes/x.json", {}
+ file "nodes/x.json", { "normal" => { "tags" => [] } }
file "policies/x-1.0.0.json", {}
file "policies/blah-1.0.0.json", {}
file "policy_groups/x.json", { "policies" => { "x" => { "revision_id" => "1.0.0" }, "blah" => { "revision_id" => "1.0.0" } } }
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 2f6747c9af..dcbc34a157 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -66,6 +66,8 @@ require "chef/util/file_edit"
require "chef/config"
+require "chef/chef_fs/file_system_cache"
+
if ENV["CHEF_FIPS"] == "1"
Chef::Config.init_openssl
end
@@ -152,6 +154,8 @@ RSpec.configure do |config|
config.filter_run_excluding :unix_only => true unless unix?
config.filter_run_excluding :aix_only => true unless aix?
config.filter_run_excluding :debian_family_only => true unless debian_family?
+ config.filter_run_excluding :linux_only => true unless linux?
+ config.filter_run_excluding :non_linux_only => true if linux?
config.filter_run_excluding :supports_cloexec => true unless supports_cloexec?
config.filter_run_excluding :selinux_only => true unless selinux_enabled?
config.filter_run_excluding :requires_root => true unless root?
@@ -200,6 +204,8 @@ RSpec.configure do |config|
config.before(:each) do
Chef.reset!
+ Chef::ChefFS::FileSystemCache.instance.reset!
+
Chef::Config.reset
# By default, treat deprecation warnings as errors in tests.
diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb
index 9ba56a15e3..783429161a 100644
--- a/spec/support/platform_helpers.rb
+++ b/spec/support/platform_helpers.rb
@@ -138,6 +138,10 @@ def freebsd?
!!(RUBY_PLATFORM =~ /freebsd/)
end
+def linux?
+ !!(RUBY_PLATFORM =~ /linux/)
+end
+
def debian_family?
!!(ohai[:platform_family] == "debian")
end
diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb
index 398d90dff0..01df9ab1a7 100644
--- a/spec/support/shared/integration/knife_support.rb
+++ b/spec/support/shared/integration/knife_support.rb
@@ -20,6 +20,7 @@ require "chef/knife"
require "chef/application/knife"
require "logger"
require "chef/log"
+require "chef/chef_fs/file_system_cache"
module KnifeSupport
DEBUG = ENV["DEBUG"]
@@ -70,6 +71,9 @@ module KnifeSupport
Chef::Config[:verbosity] = ( DEBUG ? 2 : 0 )
instance.config[:config_file] = File.join(CHEF_SPEC_DATA, "null_config.rb")
+ # Ensure the ChefFS cache is empty
+ Chef::ChefFS::FileSystemCache.instance.reset!
+
# Configure chef with a (mostly) blank knife.rb
# We set a global and then mutate it in our stub knife.rb so we can be
# extra sure that we're not loading someone's real knife.rb and then
diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb
index cb539ffbc3..ee3438da70 100644
--- a/spec/support/shared/unit/provider/file.rb
+++ b/spec/support/shared/unit/provider/file.rb
@@ -683,6 +683,31 @@ shared_examples_for Chef::Provider::File do
end
end
+ context "do_resolv_conf_fixup" do
+ %w{/resolv.conf /etc/resolv.con /etc/foo/resolv.conf /c/resolv.conf}.each do |path|
+ context "when managing #{path}" do
+ let(:resource_path) { path }
+ it "does not reload the nameservers" do
+ expect(Resolv::DefaultResolver).not_to receive(:replace_resolvers)
+ provider.send(:do_resolv_conf_fixup)
+ end
+ end
+ end
+ context "when managing /etc/resolv.conf", linux_only: true do
+ let(:resource_path) { "/etc/resolv.conf" }
+ it "reloads the nameservers on linux" do
+ expect(Resolv::DefaultResolver).to receive(:replace_resolvers)
+ provider.send(:do_resolv_conf_fixup)
+ end
+ end
+ context "when managing /etc/resolv.conf", non_linux_only: true do
+ let(:resource_path) { "/etc/resolv.conf" }
+ it "does not reload the nameservers on non-linux" do
+ expect(Resolv::DefaultResolver).not_to receive(:replace_resolvers)
+ provider.send(:do_resolv_conf_fixup)
+ end
+ end
+ end
end
context "action delete" do
diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb
index b1931414cc..686ae745d8 100644
--- a/spec/unit/application/solo_spec.rb
+++ b/spec/unit/application/solo_spec.rb
@@ -120,9 +120,10 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
expect(app).to receive(:open).with("http://junglist.gen.nz/recipes.tgz").and_yield(tarfile)
expect(File).to receive(:open).with("#{Dir.tmpdir}/chef-solo/recipes.tgz", "wb").and_yield(target_file)
- shellout = instance_double("Mixlib::ShellOut", run_command: nil, error!: nil, stdout: "")
+ archive = double(Mixlib::Archive)
- expect(app).to receive(:shell_out!).with("tar zxvf #{Dir.tmpdir}/chef-solo/recipes.tgz -C #{Dir.tmpdir}/chef-solo").and_return(shellout)
+ expect(Mixlib::Archive).to receive(:new).with("#{Dir.tmpdir}/chef-solo/recipes.tgz").and_return(archive)
+ expect(archive).to receive(:extract).with("#{Dir.tmpdir}/chef-solo", { perms: false, ignore: /^\.$/ })
app.reconfigure
expect(target_file.string).to eq("remote_tarball_content")
end
@@ -136,11 +137,10 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
Chef::Config[:cookbook_path] = "#{Dir.tmpdir}/chef-solo/cookbooks"
expect(FileUtils).to receive(:mkdir_p).with("#{Dir.tmpdir}/chef-solo").and_return(true)
- allow(Chef::Mixin::Command).to receive(:run_command).and_return(true)
+ archive = double(Mixlib::Archive)
- shellout = instance_double("Mixlib::ShellOut", run_command: nil, error!: nil, stdout: "")
-
- expect(app).to receive(:shell_out!).with("tar zxvf #{Dir.tmpdir}/chef-solo/recipes.tgz -C #{Dir.tmpdir}/chef-solo").and_return(shellout)
+ expect(Mixlib::Archive).to receive(:new).with("#{Dir.tmpdir}/chef-solo/recipes.tgz").and_return(archive)
+ expect(archive).to receive(:extract).with("#{Dir.tmpdir}/chef-solo", { perms: false, ignore: /^\.$/ })
expect(app).to receive(:fetch_recipe_tarball).ordered
expect(Chef::ConfigFetcher).to receive(:new).ordered.and_return(config_fetcher)
app.reconfigure
diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb
index 7def2f5749..81ea161bfe 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -120,8 +120,8 @@ describe Chef::CookbookVersion do
# Used to test file-specificity related file lookups
let(:node) do
Chef::Node.new.tap do |n|
- n.set[:platform] = "ubuntu"
- n.set[:platform_version] = "13.04"
+ n.normal[:platform] = "ubuntu"
+ n.normal[:platform_version] = "13.04"
n.name("testing")
end
end
@@ -203,8 +203,8 @@ describe Chef::CookbookVersion do
# Used to test file-specificity related file lookups
let(:node) do
Chef::Node.new.tap do |n|
- n.set[:platform] = "ubuntu"
- n.set[:platform_version] = "13.04"
+ n.normal[:platform] = "ubuntu"
+ n.normal[:platform_version] = "13.04"
n.name("testing")
end
end
diff --git a/spec/unit/data_collector/messages_spec.rb b/spec/unit/data_collector/messages_spec.rb
index 686e500507..b0c7e692d2 100644
--- a/spec/unit/data_collector/messages_spec.rb
+++ b/spec/unit/data_collector/messages_spec.rb
@@ -18,6 +18,7 @@
#
require "spec_helper"
+require "ffi_yajl"
require "chef/data_collector/messages/helpers"
describe Chef::DataCollector::Messages do
@@ -61,7 +62,8 @@ describe Chef::DataCollector::Messages do
end
describe '#run_end_message' do
- let(:run_status) { Chef::RunStatus.new(Chef::Node.new, Chef::EventDispatch::Dispatcher.new) }
+ let(:node) { Chef::Node.new }
+ let(:run_status) { Chef::RunStatus.new(node, Chef::EventDispatch::Dispatcher.new) }
let(:report1) { double("report1", report_data: { "status" => "updated" }) }
let(:report2) { double("report2", report_data: { "status" => "skipped" }) }
let(:reporter_data) do
@@ -76,6 +78,20 @@ describe Chef::DataCollector::Messages do
allow(run_status).to receive(:end_time).and_return(Time.now)
end
+ it "includes a valid node object in the payload" do
+ message = Chef::DataCollector::Messages.run_end_message(reporter_data)
+ expect(message["node"]).to be_an_instance_of(Chef::Node)
+ end
+
+ it "returns a sane JSON representation of the node object" do
+ node.chef_environment = "my_test_environment"
+ node.run_list.add("recipe[my_test_cookbook::default]")
+ message = FFI_Yajl::Parser.parse(Chef::DataCollector::Messages.run_end_message(reporter_data).to_json)
+
+ expect(message["node"]["chef_environment"]).to eq("my_test_environment")
+ expect(message["node"]["run_list"]).to eq(["recipe[my_test_cookbook::default]"])
+ end
+
context "when the run was successful" do
let(:required_fields) do
%w{
@@ -86,6 +102,7 @@ describe Chef::DataCollector::Messages do
expanded_run_list
message_type
message_version
+ node
node_name
organization_name
resources
@@ -136,6 +153,7 @@ describe Chef::DataCollector::Messages do
expanded_run_list
message_type
message_version
+ node
node_name
organization_name
resources
@@ -169,46 +187,4 @@ describe Chef::DataCollector::Messages do
end
end
end
-
- describe '#node_update_message' do
- let(:run_status) { Chef::RunStatus.new(Chef::Node.new, Chef::EventDispatch::Dispatcher.new) }
-
- let(:required_fields) do
- %w{
- entity_name
- entity_type
- entity_uuid
- id
- message_type
- message_version
- organization_name
- recorded_at
- remote_hostname
- requestor_name
- requestor_type
- run_id
- service_hostname
- source
- task
- user_agent
- }
- end
- let(:optional_fields) { %w{data} }
-
- it "is not missing any required fields" do
- missing_fields = required_fields.select do |key|
- !Chef::DataCollector::Messages.node_update_message(run_status).key?(key)
- end
-
- expect(missing_fields).to eq([])
- end
-
- it "does not have any extra fields" do
- extra_fields = Chef::DataCollector::Messages.node_update_message(run_status).keys.select do |key|
- !required_fields.include?(key) && !optional_fields.include?(key)
- end
-
- expect(extra_fields).to eq([])
- end
- end
end
diff --git a/spec/unit/data_collector_spec.rb b/spec/unit/data_collector_spec.rb
index 831643347b..131d6b8df9 100644
--- a/spec/unit/data_collector_spec.rb
+++ b/spec/unit/data_collector_spec.rb
@@ -156,6 +156,10 @@ describe Chef::DataCollector::Reporter do
let(:reporter) { described_class.new }
let(:run_status) { Chef::RunStatus.new(Chef::Node.new, Chef::EventDispatch::Dispatcher.new) }
+ before do
+ Chef::Config[:data_collector][:server_url] = "http://my-data-collector-server.mycompany.com"
+ end
+
describe '#run_started' do
before do
allow(reporter).to receive(:update_run_status)
@@ -490,7 +494,8 @@ describe Chef::DataCollector::Reporter do
[ Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
Errno::ECONNREFUSED, EOFError, Net::HTTPBadResponse,
- Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError ].each do |exception_class|
+ Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError,
+ Errno::EHOSTDOWN ].each do |exception_class|
context "when the block raises a #{exception_class} exception" do
it "disables the reporter" do
expect(reporter).to receive(:disable_data_collector_reporter)
@@ -515,4 +520,39 @@ describe Chef::DataCollector::Reporter do
end
end
end
+
+ describe '#validate_data_collector_server_url!' do
+ context "when server_url is empty" do
+ it "raises an exception" do
+ Chef::Config[:data_collector][:server_url] = ""
+ expect { reporter.send(:validate_data_collector_server_url!) }.to raise_error(Chef::Exceptions::ConfigurationError)
+ end
+ end
+
+ context "when server_url is not empty" do
+ context "when server_url is an invalid URI" do
+ it "raises an exception" do
+ Chef::Config[:data_collector][:server_url] = "this is not a URI"
+ expect { reporter.send(:validate_data_collector_server_url!) }.to raise_error(Chef::Exceptions::ConfigurationError)
+ end
+ end
+
+ context "when server_url is a valid URI" do
+ context "when server_url is a URI with no host" do
+ it "raises an exception" do
+ Chef::Config[:data_collector][:server_url] = "/file/uri.txt"
+ expect { reporter.send(:validate_data_collector_server_url!) }.to raise_error(Chef::Exceptions::ConfigurationError)
+ end
+
+ end
+
+ context "when server_url is a URI with a valid host" do
+ it "does not an exception" do
+ Chef::Config[:data_collector][:server_url] = "http://www.google.com/data-collector"
+ expect { reporter.send(:validate_data_collector_server_url!) }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/unit/dsl/declare_resource_spec.rb b/spec/unit/dsl/declare_resource_spec.rb
index 6dd9317c21..692e57d2e1 100644
--- a/spec/unit/dsl/declare_resource_spec.rb
+++ b/spec/unit/dsl/declare_resource_spec.rb
@@ -235,6 +235,36 @@ describe Chef::ResourceCollection do
).to eql(resource)
expect(run_context.resource_collection.all_resources.size).to eql(0)
end
+
+ it "removes pending delayed notifications" do
+ recipe.declare_resource(:zen_master, "one")
+ recipe.declare_resource(:zen_master, "two") do
+ notifies :win, "zen_master[one]"
+ end
+ recipe.delete_resource(:zen_master, "two")
+ resource = recipe.declare_resource(:zen_master, "two")
+ expect(resource.delayed_notifications).to eql([])
+ end
+
+ it "removes pending immediate notifications" do
+ recipe.declare_resource(:zen_master, "one")
+ recipe.declare_resource(:zen_master, "two") do
+ notifies :win, "zen_master[one]", :immediate
+ end
+ recipe.delete_resource(:zen_master, "two")
+ resource = recipe.declare_resource(:zen_master, "two")
+ expect(resource.immediate_notifications).to eql([])
+ end
+
+ it "removes pending before notifications" do
+ recipe.declare_resource(:zen_master, "one")
+ recipe.declare_resource(:zen_master, "two") do
+ notifies :win, "zen_master[one]", :before
+ end
+ recipe.delete_resource(:zen_master, "two")
+ resource = recipe.declare_resource(:zen_master, "two")
+ expect(resource.before_notifications).to eql([])
+ end
end
describe "run_context helpers" do
diff --git a/spec/unit/knife/cookbook_site_install_spec.rb b/spec/unit/knife/cookbook_site_install_spec.rb
index d60443d779..1549245ea3 100644
--- a/spec/unit/knife/cookbook_site_install_spec.rb
+++ b/spec/unit/knife/cookbook_site_install_spec.rb
@@ -23,6 +23,7 @@ describe Chef::Knife::CookbookSiteInstall do
let(:stdout) { StringIO.new }
let(:stderr) { StringIO.new }
let(:downloader) { Hash.new }
+ let(:archive) { double(Mixlib::Archive, extract: true) }
let(:repo) { double(:sanity_check => true, :reset_to_default_state => true,
:prepare_to_import => true, :finalize_updates_to => true,
:merge_updates_from => true) }
@@ -48,6 +49,7 @@ describe Chef::Knife::CookbookSiteInstall do
allow(File).to receive(:unlink)
allow(File).to receive(:rmtree)
allow(knife).to receive(:shell_out!).and_return(true)
+ allow(Mixlib::Archive).to receive(:new).and_return(archive)
# CookbookSiteDownload Stup
allow(knife).to receive(:download_cookbook_to).and_return(downloader)
diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb
index 9339114d2a..5ac48539e4 100644
--- a/spec/unit/knife/cookbook_site_share_spec.rb
+++ b/spec/unit/knife/cookbook_site_share_spec.rb
@@ -83,11 +83,11 @@ describe Chef::Knife::CookbookSiteShare do
@knife.run
end
- it "should print error and exit when given only 1 argument and cannot determine category" do
+ it "should use a default category when given only 1 argument and cannot determine category" do
@knife.name_args = ["cookbook_name"]
- expect(@noauth_rest).to receive(:get).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name").and_return(@bad_category_response)
- expect(@knife.ui).to receive(:fatal)
- expect { @knife.run }.to raise_error(SystemExit)
+ expect(@noauth_rest).to receive(:get).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name") { raise Net::HTTPServerException.new("404 Not Found", OpenStruct.new(code: "404")) }
+ expect(@knife).to receive(:do_upload)
+ expect { @knife.run }.to_not raise_error
end
it "should print error and exit when given only 1 argument and Chef::ServerAPI throws an exception" do
diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb
index 57ad3c0c25..e40f454c0b 100644
--- a/spec/unit/node/attribute_spec.rb
+++ b/spec/unit/node/attribute_spec.rb
@@ -218,7 +218,7 @@ describe Chef::Node::Attribute do
end
it "gives the value at each level of precedence for a path spec" do
- expected = [["set_unless_enabled?", false],
+ expected = [
%w{default default},
%w{env_default env_default},
%w{role_default role_default},
@@ -417,12 +417,6 @@ describe Chef::Node::Attribute do
expect(@attributes.normal["foo"]["bar"]).to eq(:baz)
end
- it "should optionally skip setting the value if one already exists" do
- @attributes.set_unless_value_present = true
- @attributes.normal["hostname"] = "bar"
- expect(@attributes["hostname"]).to eq("latte")
- end
-
it "does not support ||= when setting" do
# This is a limitation of auto-vivification.
# Users who need this behavior can use set_unless and friends
@@ -493,6 +487,7 @@ describe Chef::Node::Attribute do
end
it "should return true if an attribute exists but is set to nil using dot notation" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(@attributes.music.deeper.has_key?("gates_of_ishtar")).to eq(true)
end
@@ -533,10 +528,12 @@ describe Chef::Node::Attribute do
describe "method_missing" do
it "should behave like a [] lookup" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(@attributes.music.mastodon).to eq("rocks")
end
it "should allow the last method to set a value if it has an = sign on the end" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
@attributes.normal.music.mastodon = %w{dream still shining}
expect(@attributes.normal.music.mastodon).to eq(%w{dream still shining})
end
@@ -577,7 +574,7 @@ describe Chef::Node::Attribute do
it "should yield lower if we go deeper" do
collect = Array.new
- @attributes.one.keys.each do |k|
+ @attributes["one"].keys.each do |k|
collect << k
end
expect(collect.include?("two")).to eq(true)
@@ -587,7 +584,7 @@ describe Chef::Node::Attribute do
end
it "should not raise an exception if one of the hashes has a nil value on a deep lookup" do
- expect { @attributes.place.keys { |k| } }.not_to raise_error
+ expect { @attributes["place"].keys { |k| } }.not_to raise_error
end
end
@@ -1171,6 +1168,7 @@ describe Chef::Node::Attribute do
end
it "raises an error when using `attr=value`" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect { @attributes.new_key = "new value" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
end
diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb
index f57ed459cd..fe4e50d1bd 100644
--- a/spec/unit/node/immutable_collections_spec.rb
+++ b/spec/unit/node/immutable_collections_spec.rb
@@ -95,6 +95,10 @@ describe Chef::Node::ImmutableMash do
:replace,
:select!,
:shift,
+ :write,
+ :write!,
+ :unlink,
+ :unlink!,
].each do |mutator|
it "doesn't allow mutation via `#{mutator}'" do
expect { @immutable_mash.send(mutator) }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb
new file mode 100644
index 0000000000..5319ba4a35
--- /dev/null
+++ b/spec/unit/node/vivid_mash_spec.rb
@@ -0,0 +1,377 @@
+#
+# Copyright:: Copyright 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 "chef/node/attribute_collections"
+
+describe Chef::Node::VividMash do
+ class Root
+ attr_accessor :top_level_breadcrumb
+ end
+
+ let(:root) { Root.new }
+
+ let(:vivid) do
+ expect(root).to receive(:reset_cache).at_least(:once).with(nil)
+ Chef::Node::VividMash.new(root,
+ { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil }
+ )
+ end
+
+ def with_breadcrumb(key)
+ expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
+ expect(root).to receive(:top_level_breadcrumb=).with(key).at_least(:once).and_call_original
+ end
+
+ context "#read" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "reads hashes deeply" do
+ with_breadcrumb("one")
+ expect(vivid.read("one", "two", "three")).to eql("four")
+ end
+
+ it "does not trainwreck when hitting hash keys that do not exist" do
+ with_breadcrumb("one")
+ expect(vivid.read("one", "five", "six")).to eql(nil)
+ end
+
+ it "does not trainwreck when hitting an array with an out of bounds index" do
+ with_breadcrumb("array")
+ expect(vivid.read("array", 5, "one")).to eql(nil)
+ end
+
+ it "does not trainwreck when hitting an array with a string key" do
+ with_breadcrumb("array")
+ expect(vivid.read("array", "one", "two")).to eql(nil)
+ end
+
+ it "does not trainwreck when traversing a nil" do
+ with_breadcrumb("nil")
+ expect(vivid.read("nil", "one", "two")).to eql(nil)
+ end
+ end
+
+ context "#exist?" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "true if there's a hash key there" do
+ with_breadcrumb("one")
+ expect(vivid.exist?("one", "two", "three")).to be true
+ end
+
+ it "true for intermediate hashes" do
+ with_breadcrumb("one")
+ expect(vivid.exist?("one")).to be true
+ end
+
+ it "true for arrays that exist" do
+ with_breadcrumb("array")
+ expect(vivid.exist?("array", 1)).to be true
+ end
+
+ it "true when the value of the key is nil" do
+ with_breadcrumb("nil")
+ expect(vivid.exist?("nil")).to be true
+ end
+
+ it "false when attributes don't exist" do
+ with_breadcrumb("one")
+ expect(vivid.exist?("one", "five", "six")).to be false
+ end
+
+ it "false when traversing a non-container" do
+ with_breadcrumb("one")
+ expect(vivid.exist?("one", "two", "three", "four")).to be false
+ end
+
+ it "false when an array index does not exist" do
+ with_breadcrumb("array")
+ expect(vivid.exist?("array", 3)).to be false
+ end
+
+ it "false when traversing a nil" do
+ with_breadcrumb("nil")
+ expect(vivid.exist?("nil", "foo", "bar")).to be false
+ end
+ end
+
+ context "#read!" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "reads hashes deeply" do
+ with_breadcrumb("one")
+ expect(vivid.read!("one", "two", "three")).to eql("four")
+ end
+
+ it "reads arrays deeply" do
+ with_breadcrumb("array")
+ expect(vivid.read!("array", 1)).to eql(1)
+ end
+
+ it "throws an exception when attributes do not exist" do
+ with_breadcrumb("one")
+ expect { vivid.read!("one", "five", "six") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+
+ it "throws an exception when traversing a non-container" do
+ with_breadcrumb("one")
+ expect { vivid.read!("one", "two", "three", "four") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+
+ it "throws an exception when an array element does not exist" do
+ with_breadcrumb("array")
+ expect { vivid.read!("array", 3) }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+ end
+
+ context "#write" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should write into hashes" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five", "six")
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+
+ it "should deeply autovivify" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
+ end
+
+ it "should raise an exception if you overwrite an array with a hash" do
+ with_breadcrumb("array")
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ vivid.write("array", "five", "six")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => "six" }, "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through an array with a hash" do
+ with_breadcrumb("array")
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ vivid.write("array", "five", "six", "seven")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => { "six" => "seven" } }, "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a string with a hash" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "two", "three", "four", "five")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => "five" } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a string with a hash" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "two", "three", "four", "five", "six")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => { "five" => "six" } } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a nil with a hash" do
+ with_breadcrumb("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ vivid.write("nil", "one", "two")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => "two" } })
+ end
+
+ it "should raise an exception if you traverse through a nil with a hash" do
+ with_breadcrumb("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ vivid.write("nil", "one", "two", "three")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => { "two" => "three" } } })
+ end
+
+ it "writes with a block" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five") { "six" }
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+ end
+
+ context "#write!" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should write into hashes" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five", "six")
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+
+ it "should deeply autovivify" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
+ end
+
+ it "should raise an exception if you overwrite an array with a hash" do
+ with_breadcrumb("array")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("array", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through an array with a hash" do
+ with_breadcrumb("array")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("array", "five", "six", "seven") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a string with a hash" do
+ with_breadcrumb("one")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("one", "two", "three", "four", "five") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a string with a hash" do
+ with_breadcrumb("one")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("one", "two", "three", "four", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a nil with a hash" do
+ with_breadcrumb("nil")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("nil", "one", "two") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a nil with a hash" do
+ with_breadcrumb("nil")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("nil", "one", "two", "three") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "writes with a block" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five") { "six" }
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+ end
+
+ context "#unlink" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should return nil if the keys don't already exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
+ expect(root).not_to receive(:reset_cache)
+ expect(vivid.unlink("five", "six", "seven", "eight")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink hashes" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink array elements" do
+ with_breadcrumb("array")
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ expect(vivid.unlink("array", 2)).to eql(2)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
+ end
+
+ it "should unlink nil" do
+ with_breadcrumb("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(vivid.unlink("nil")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
+ end
+
+ it "should traverse a nil and safely do nothing" do
+ with_breadcrumb("nil")
+ expect(root).not_to receive(:reset_cache)
+ expect(vivid.unlink("nil", "foo")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+ end
+
+ context "#unlink!" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should raise an exception if the keys don't already exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.unlink!("five", "six", "seven", "eight") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink! hashes" do
+ with_breadcrumb("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink! array elements" do
+ with_breadcrumb("array")
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ expect(vivid.unlink!("array", 2)).to eql(2)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
+ end
+
+ it "should unlink! nil" do
+ with_breadcrumb("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(vivid.unlink!("nil")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
+ end
+
+ it "should raise an exception if it traverses a nil" do
+ with_breadcrumb("nil")
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.unlink!("nil", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+ end
+end
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 923b488f72..72731c927f 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -233,60 +233,69 @@ describe Chef::Node do
end
it "should let you go deep with attribute?" do
- node.set["battles"]["people"]["wonkey"] = true
+ node.normal["battles"]["people"]["wonkey"] = true
expect(node["battles"]["people"].attribute?("wonkey")).to eq(true)
expect(node["battles"]["people"].attribute?("snozzberry")).to eq(false)
end
it "does not allow you to set an attribute via method_missing" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect { node.sunshine = "is bright" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
end
it "should allow you get get an attribute via method_missing" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
node.default.sunshine = "is bright"
expect(node.sunshine).to eql("is bright")
end
describe "normal attributes" do
it "should allow you to set an attribute with set, without pre-declaring a hash" do
- node.set[:snoopy][:is_a_puppy] = true
+ node.normal[:snoopy][:is_a_puppy] = true
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
+ it "should allow you to set an attribute with set_unless with method_missing but emit a deprecation warning" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ node.normal_unless.snoopy.is_a_puppy = false
+ expect(node[:snoopy][:is_a_puppy]).to eq(false)
+ end
+
it "should allow you to set an attribute with set_unless" do
- node.set_unless[:snoopy][:is_a_puppy] = false
+ node.normal_unless[:snoopy][:is_a_puppy] = false
expect(node[:snoopy][:is_a_puppy]).to eq(false)
end
it "should not allow you to set an attribute with set_unless if it already exists" do
- node.set[:snoopy][:is_a_puppy] = true
- node.set_unless[:snoopy][:is_a_puppy] = false
+ node.normal[:snoopy][:is_a_puppy] = true
+ node.normal_unless[:snoopy][:is_a_puppy] = false
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
it "should allow you to set an attribute with set_unless if is a nil value" do
node.attributes.normal = { snoopy: { is_a_puppy: nil } }
- node.set_unless[:snoopy][:is_a_puppy] = false
+ node.normal_unless[:snoopy][:is_a_puppy] = false
expect(node[:snoopy][:is_a_puppy]).to eq(false)
end
it "should allow you to set a value after a set_unless" do
# this tests for set_unless_present state bleeding between statements CHEF-3806
- node.set_unless[:snoopy][:is_a_puppy] = false
- node.set[:snoopy][:is_a_puppy] = true
+ node.normal_unless[:snoopy][:is_a_puppy] = false
+ node.normal[:snoopy][:is_a_puppy] = true
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
it "should let you set a value after a 'dangling' set_unless" do
# this tests for set_unless_present state bleeding between statements CHEF-3806
- node.set[:snoopy][:is_a_puppy] = "what"
- node.set_unless[:snoopy][:is_a_puppy]
- node.set[:snoopy][:is_a_puppy] = true
+ node.normal[:snoopy][:is_a_puppy] = "what"
+ node.normal_unless[:snoopy][:is_a_puppy]
+ node.normal[:snoopy][:is_a_puppy] = true
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
it "auto-vivifies attributes created via method syntax" do
- node.set.fuu.bahrr.baz = "qux"
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ node.normal.fuu.bahrr.baz = "qux"
expect(node.fuu.bahrr.baz).to eq("qux")
end
@@ -295,6 +304,20 @@ describe Chef::Node do
node.tag("three", "four")
expect(node["tags"]).to eq(%w{one two three four})
end
+
+ it "set is a deprecated alias for normal" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef).to receive(:log_deprecation).with(/set is deprecated/)
+ node.set[:snoopy][:is_a_puppy] = true
+ expect(node[:snoopy][:is_a_puppy]).to eq(true)
+ end
+
+ it "set_unless is a deprecated alias for normal_unless" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef).to receive(:log_deprecation).with(/set_unless is deprecated/)
+ node.set_unless[:snoopy][:is_a_puppy] = false
+ expect(node[:snoopy][:is_a_puppy]).to eq(false)
+ end
end
describe "default attributes" do
@@ -329,10 +352,41 @@ describe Chef::Node do
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
+ it "does not exhibit chef/chef/issues/5005 bug" do
+ node.env_default["a"]["r1"]["g"]["u"] = "u1"
+ node.default_unless["a"]["r1"]["g"]["r"] = "r"
+ expect(node["a"]["r1"]["g"]["u"]).to eql("u1")
+ end
+
it "auto-vivifies attributes created via method syntax" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
node.default.fuu.bahrr.baz = "qux"
expect(node.fuu.bahrr.baz).to eq("qux")
end
+
+ it "default_unless correctly resets the deep merge cache" do
+ node.normal["tags"] = [] # this sets our top-level breadcrumb
+ node.default_unless["foo"]["bar"] = "NK-19V"
+ expect(node["foo"]["bar"]).to eql("NK-19V")
+ node.default_unless["foo"]["baz"] = "NK-33"
+ expect(node["foo"]["baz"]).to eql("NK-33")
+ end
+
+ it "normal_unless correctly resets the deep merge cache" do
+ node.normal["tags"] = [] # this sets our top-level breadcrumb
+ node.normal_unless["foo"]["bar"] = "NK-19V"
+ expect(node["foo"]["bar"]).to eql("NK-19V")
+ node.normal_unless["foo"]["baz"] = "NK-33"
+ expect(node["foo"]["baz"]).to eql("NK-33")
+ end
+
+ it "override_unless correctly resets the deep merge cache" do
+ node.normal["tags"] = [] # this sets our top-level breadcrumb
+ node.override_unless["foo"]["bar"] = "NK-19V"
+ expect(node["foo"]["bar"]).to eql("NK-19V")
+ node.override_unless["foo"]["baz"] = "NK-33"
+ expect(node["foo"]["baz"]).to eql("NK-33")
+ end
end
describe "override attributes" do
@@ -368,6 +422,7 @@ describe Chef::Node do
end
it "auto-vivifies attributes created via method syntax" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
node.override.fuu.bahrr.baz = "qux"
expect(node.fuu.bahrr.baz).to eq("qux")
end
@@ -453,8 +508,9 @@ describe Chef::Node do
expect( node["mysql"]["server"][0]["port"] ).to be_nil
end
- it "does not have a horrible error message when mistaking arrays for hashes" do
- expect { node.rm("mysql", "server", "port") }.to raise_error(TypeError, "Wrong type in index of attribute (did you use a Hash index on an Array?)")
+ it "when mistaking arrays for hashes, it considers the value removed and does nothing" do
+ node.rm("mysql", "server", "port")
+ expect(node["mysql"]["server"][0]["port"]).to eql(3456)
end
end
end
@@ -706,6 +762,7 @@ describe Chef::Node do
#
describe "deep merge attribute cache edge conditions" do
it "does not error with complicated attribute substitution" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
node.default["chef_attribute_hell"]["attr1"] = "attribute1"
node.default["chef_attribute_hell"]["attr2"] = "#{node.chef_attribute_hell.attr1}/attr2"
expect { node.default["chef_attribute_hell"]["attr3"] = "#{node.chef_attribute_hell.attr2}/attr3" }.not_to raise_error
@@ -720,6 +777,7 @@ describe Chef::Node do
end
it "method interpolation syntax also works" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
node.default["passenger"]["version"] = "4.0.57"
node.default["passenger"]["root_path"] = "passenger-#{node['passenger']['version']}"
node.default["passenger"]["root_path_2"] = "passenger-#{node.passenger['version']}"
@@ -729,6 +787,7 @@ describe Chef::Node do
end
it "should raise an ArgumentError if you ask for an attribute that doesn't exist via method_missing" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect { node.sunshine }.to raise_error(NoMethodError)
end
@@ -744,6 +803,51 @@ describe Chef::Node do
expect(seen_attributes["sunshine"]).to eq("is bright")
expect(seen_attributes["canada"]).to eq("is a nice place")
end
+
+ describe "functional attribute API" do
+ # deeper functional testing of this API is in the VividMash spec tests
+ it "should have an exist? function" do
+ node.default["foo"]["bar"] = "baz"
+ expect(node.exist?("foo", "bar")).to be true
+ expect(node.exist?("bar", "foo")).to be false
+ end
+
+ it "should have a read function" do
+ node.override["foo"]["bar"] = "baz"
+ expect(node.read("foo", "bar")).to eql("baz")
+ expect(node.read("bar", "foo")).to eql(nil)
+ end
+
+ it "should have a read! function" do
+ node.override["foo"]["bar"] = "baz"
+ expect(node.read!("foo", "bar")).to eql("baz")
+ expect { node.read!("bar", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+
+ it "delegates write(:level) to node.level.write()" do
+ node.write(:default, "foo", "bar", "baz")
+ expect(node.default["foo"]["bar"]).to eql("baz")
+ end
+
+ it "delegates write!(:level) to node.level.write!()" do
+ node.write!(:default, "foo", "bar", "baz")
+ expect(node.default["foo"]["bar"]).to eql("baz")
+ node.default["bar"] = true
+ expect { node.write!(:default, "bar", "foo", "baz") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ end
+
+ it "delegates unlink(:level) to node.level.unlink()" do
+ node.default["foo"]["bar"] = "baz"
+ expect(node.unlink(:default, "foo", "bar")).to eql("baz")
+ expect(node.unlink(:default, "bar", "foo")).to eql(nil)
+ end
+
+ it "delegates unlink!(:level) to node.level.unlink!()" do
+ node.default["foo"]["bar"] = "baz"
+ expect(node.unlink!(:default, "foo", "bar")).to eql("baz")
+ expect { node.unlink!(:default, "bar", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+ end
end
describe "consuming json" do
@@ -789,8 +893,8 @@ describe Chef::Node do
it "should add json attributes to the node" do
node.consume_external_attrs(@ohai_data, { "one" => "two", "three" => "four" })
- expect(node.one).to eql("two")
- expect(node.three).to eql("four")
+ expect(node["one"]).to eql("two")
+ expect(node["three"]).to eql("four")
end
it "should set the tags attribute to an empty array if it is not already defined" do
@@ -824,17 +928,17 @@ describe Chef::Node do
it "deep merges attributes instead of overwriting them" do
node.consume_external_attrs(@ohai_data, "one" => { "two" => { "three" => "four" } })
- expect(node.one.to_hash).to eq({ "two" => { "three" => "four" } })
+ expect(node["one"].to_hash).to eq({ "two" => { "three" => "four" } })
node.consume_external_attrs(@ohai_data, "one" => { "abc" => "123" })
node.consume_external_attrs(@ohai_data, "one" => { "two" => { "foo" => "bar" } })
- expect(node.one.to_hash).to eq({ "two" => { "three" => "four", "foo" => "bar" }, "abc" => "123" })
+ expect(node["one"].to_hash).to eq({ "two" => { "three" => "four", "foo" => "bar" }, "abc" => "123" })
end
it "gives attributes from JSON priority when deep merging" do
node.consume_external_attrs(@ohai_data, "one" => { "two" => { "three" => "four" } })
- expect(node.one.to_hash).to eq({ "two" => { "three" => "four" } })
+ expect(node["one"].to_hash).to eq({ "two" => { "three" => "four" } })
node.consume_external_attrs(@ohai_data, "one" => { "two" => { "three" => "forty-two" } })
- expect(node.one.to_hash).to eq({ "two" => { "three" => "forty-two" } })
+ expect(node["one"].to_hash).to eq({ "two" => { "three" => "forty-two" } })
end
end
@@ -1036,10 +1140,10 @@ describe Chef::Node do
end
it "sets attributes from the files" do
- expect(node.ldap_server).to eql("ops1prod")
- expect(node.ldap_basedn).to eql("dc=hjksolutions,dc=com")
- expect(node.ldap_replication_password).to eql("forsure")
- expect(node.smokey).to eql("robinson")
+ expect(node["ldap_server"]).to eql("ops1prod")
+ expect(node["ldap_basedn"]).to eql("dc=hjksolutions,dc=com")
+ expect(node["ldap_replication_password"]).to eql("forsure")
+ expect(node["smokey"]).to eql("robinson")
end
it "gives a sensible error when attempting to load a missing attributes file" do
@@ -1083,8 +1187,8 @@ describe Chef::Node do
it "should load a node from a ruby file" do
node.from_file(File.expand_path(File.join(CHEF_SPEC_DATA, "nodes", "test.rb")))
expect(node.name).to eql("test.example.com-short")
- expect(node.sunshine).to eql("in")
- expect(node.something).to eql("else")
+ expect(node["sunshine"]).to eql("in")
+ expect(node["something"]).to eql("else")
expect(node.run_list).to eq(["operations-master", "operations-monitoring"])
end
@@ -1562,4 +1666,19 @@ describe Chef::Node do
end
end
+ describe "method_missing handling" do
+ it "should have an #empty? method via Chef::Node::Attribute" do
+ node.default["foo"] = "bar"
+ expect(node.empty?).to be false
+ end
+
+ it "it should correctly implement #respond_to?" do
+ expect(node.respond_to?(:empty?)).to be true
+ end
+
+ it "it should correctly retrieve the method with #method" do
+ expect(node.method(:empty?)).to be_kind_of(Method)
+ end
+ end
+
end
diff --git a/spec/unit/provider/package/aix_spec.rb b/spec/unit/provider/package/aix_spec.rb
index 6940874a43..2b574bb7df 100644
--- a/spec/unit/provider/package/aix_spec.rb
+++ b/spec/unit/provider/package/aix_spec.rb
@@ -73,6 +73,19 @@ describe Chef::Provider::Package::Aix do
expect(@new_resource.version).to eq("3.3.12.0")
end
+ it "should warn if the package is not a fileset" do
+ info = "samba.base:samba.base.samples:3.3.12.0::COMMITTED:I:Samba for AIX:
+ /etc/objrepos:samba.base:3.3.12.0::COMMITTED:I:Samba for AIX:"
+ status = double("Status", :stdout => info, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(Chef::Log).to receive(:warn).once.with(%r{bff package by product name})
+ @provider.load_current_resource
+
+ expect(@provider.current_resource.package_name).to eq("samba.base")
+ expect(@new_resource.version).to eq("3.3.12.0")
+ end
+
it "should return the current version installed if found by lslpp" do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
@stdout = StringIO.new(@bffinfo)
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index df0a1da9a2..8838c26b71 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -72,7 +72,7 @@ describe Chef::Provider::Package::Zypper do
provider.load_current_resource
end
- it "should set the installed version if zypper info has one" do
+ it "should set the installed version if zypper info has one (zypper version < 1.13.0)" do
status = double(:stdout => "Version: 1.0\nInstalled: Yes\n", :exitstatus => 0)
allow(provider).to receive(:shell_out!).and_return(status)
@@ -80,7 +80,15 @@ describe Chef::Provider::Package::Zypper do
provider.load_current_resource
end
- it "should set the candidate version if zypper info has one" do
+ it "should set the installed version if zypper info has one (zypper version >= 1.13.0)" do
+ status = double(:stdout => "Version : 1.0 \nInstalled : Yes \n", :exitstatus => 0)
+
+ allow(provider).to receive(:shell_out!).and_return(status)
+ expect(current_resource).to receive(:version).with(["1.0"]).and_return(true)
+ provider.load_current_resource
+ end
+
+ it "should set the candidate version if zypper info has one (zypper version < 1.13.0)" do
status = double(:stdout => "Version: 1.0\nInstalled: No\nStatus: out-of-date (version 0.9 installed)", :exitstatus => 0)
allow(provider).to receive(:shell_out!).and_return(status)
@@ -88,6 +96,14 @@ describe Chef::Provider::Package::Zypper do
expect(provider.candidate_version).to eql(["1.0"])
end
+ it "should set the candidate version if zypper info has one (zypper version >= 1.13.0)" do
+ status = double(:stdout => "Version : 1.0 \nInstalled : No \nStatus : out-of-date (version 0.9 installed)", :exitstatus => 0)
+
+ allow(provider).to receive(:shell_out!).and_return(status)
+ provider.load_current_resource
+ expect(provider.candidate_version).to eql(["1.0"])
+ end
+
it "should return the current resouce" do
expect(provider.load_current_resource).to eql(current_resource)
end
diff --git a/spec/unit/provider/powershell_script_spec.rb b/spec/unit/provider/powershell_script_spec.rb
index 5b5c783986..96869ff31c 100644
--- a/spec/unit/provider/powershell_script_spec.rb
+++ b/spec/unit/provider/powershell_script_spec.rb
@@ -43,8 +43,8 @@ describe Chef::Provider::PowershellScript, "action_run" do
allow(Chef::Platform).to receive(:windows_nano_server?).and_return(true)
allow(provider).to receive(:is_forced_32bit).and_return(false)
os_info_double = double("os_info")
- allow(provider.run_context.node.kernel).to receive(:os_info).and_return(os_info_double)
- allow(os_info_double).to receive(:system_directory).and_return("C:\\Windows\\system32")
+ allow(provider.run_context.node["kernel"]).to receive(:[]).with("os_info").and_return(os_info_double)
+ allow(os_info_double).to receive(:[]).with("system_directory").and_return("C:\\Windows\\system32")
end
it "sets the -Command flag as the last flag" do
@@ -58,8 +58,8 @@ describe Chef::Provider::PowershellScript, "action_run" do
allow(Chef::Platform).to receive(:windows_nano_server?).and_return(false)
allow(provider).to receive(:is_forced_32bit).and_return(false)
os_info_double = double("os_info")
- allow(provider.run_context.node.kernel).to receive(:os_info).and_return(os_info_double)
- allow(os_info_double).to receive(:system_directory).and_return("C:\\Windows\\system32")
+ allow(provider.run_context.node["kernel"]).to receive(:[]).with("os_info").and_return(os_info_double)
+ allow(os_info_double).to receive(:[]).with("system_directory").and_return("C:\\Windows\\system32")
end
it "sets the -File flag as the last flag" do
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index 70164f0a9b..3c30f96b20 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -266,6 +266,27 @@ describe Chef::Recipe do
end
end
+ class Coerced < Chef::Resource
+ resource_name :coerced
+ provides :coerced
+ default_action :whatever
+ property :package_name, [String, Array], coerce: proc { |x| [x].flatten }, name_property: true
+ def after_created
+ Array(action).each do |action|
+ run_action(action)
+ end
+ end
+ action :whatever do
+ package_name # unlazy the package_name
+ end
+ end
+
+ it "does not emit 3694 when the name_property is unlazied by running it at compile_time" do
+ recipe.coerced "string"
+ expect(Chef).to_not receive(:log_deprecation)
+ recipe.coerced "string"
+ end
+
it "validating resources via build_resource" do
expect {recipe.build_resource(:remote_file, "klopp") do
source Chef::DelayedEvaluator.new { "http://chef.io" }
diff --git a/spec/unit/run_context_spec.rb b/spec/unit/run_context_spec.rb
index 7b2a27e9f6..234cd3c9e1 100644
--- a/spec/unit/run_context_spec.rb
+++ b/spec/unit/run_context_spec.rb
@@ -153,8 +153,8 @@ describe Chef::RunContext do
let(:chef_repo_path) { File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) }
let(:node) {
node = Chef::Node.new
- node.set[:platform] = "ubuntu"
- node.set[:platform_version] = "13.04"
+ node.normal[:platform] = "ubuntu"
+ node.normal[:platform_version] = "13.04"
node.name("testing")
node
}
diff --git a/spec/unit/shell/shell_session_spec.rb b/spec/unit/shell/shell_session_spec.rb
index 22f3dc6f0c..259e6096a4 100644
--- a/spec/unit/shell/shell_session_spec.rb
+++ b/spec/unit/shell/shell_session_spec.rb
@@ -158,7 +158,7 @@ describe Shell::SoloSession do
it "keeps json attribs and passes them to the node for consumption" do
@session.node_attributes = { "besnard_lakes" => "are_the_dark_horse" }
- expect(@session.node.besnard_lakes).to eq("are_the_dark_horse")
+ expect(@session.node["besnard_lakes"]).to eq("are_the_dark_horse")
#pending "1) keep attribs in an ivar 2) pass them to the node 3) feed them to the node on reset"
end