diff options
author | AbhishekKr <abhikumar163@gmail.com> | 2016-10-06 21:35:22 +0530 |
---|---|---|
committer | AbhishekKr <abhikumar163@gmail.com> | 2016-10-06 21:35:22 +0530 |
commit | 08654df29d276ec9754f8fa2272855e1d6b73d5b (patch) | |
tree | 5caf0c8429c74d17981fbec495bc230569631131 | |
parent | ff19b559b6bd139e6701cfcf4f7b065fb01f9fa7 (diff) | |
parent | 81300c7168df0c3e6171b3dbfe09f92c28b6f2a1 (diff) | |
download | chef-08654df29d276ec9754f8fa2272855e1d6b73d5b.tar.gz |
Merge branch 'master' of https://github.com/chef/chef
95 files changed, 2117 insertions, 845 deletions
diff --git a/.gitignore b/.gitignore index 1e60843467..be88d2c809 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ kitchen-tests/nodes/* # Temporary files present during spec runs spec/data/test-dir /config/ + +# acceptance binstubs +acceptance/bin/* diff --git a/.travis.yml b/.travis.yml index 58c10dffa2..3fb6461607 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,12 +21,12 @@ before_script: branches: only: - master - - 10-stable - 11-stable env: global: - FORCE_FFI_YAJL=ext + - BUNDLE_ENABLE_TRAMPOLINE=1 matrix: include: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dccc3860b..0ddd22612a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,66 @@ # Change Log +## [v12.14.89](https://github.com/chef/chef/tree/v12.14.89) (2016-09-22) +[Full Changelog](https://github.com/chef/chef/compare/v12.14.77...v12.14.89) + +**Fixed Bugs:** + +- Revert "Verify systemd\_unit file during create" [\#5326](https://github.com/chef/chef/pull/5326) ([mwrock](https://github.com/mwrock)) +- Fix method\_access and array handling in node presenter [\#5351](https://github.com/chef/chef/pull/5351) ([lamont-granquist](https://github.com/lamont-granquist)) +- Fixed undefined short\_cksum method issue and checksum in uppercase issue for windows\_package resource. [\#5332](https://github.com/chef/chef/pull/5332) ([Aliasgar16](https://github.com/Aliasgar16)) +- Fix makecache action name in yum\_repository [\#5348](https://github.com/chef/chef/pull/5348) ([tas50](https://github.com/tas50)) + +## [v12.14.77](https://github.com/chef/chef/tree/v12.14.77) (2016-09-19) +[Full Changelog](https://github.com/chef/chef/compare/v12.14.60...v12.14.77) + +**Fixed Bugs:** + +- Revert supports\[:manage\_home\] behavior [\#5322](https://github.com/chef/chef/pull/5322) ([lamont-granquist](https://github.com/lamont-granquist)) +- Preserve the extension of the file in the rendered tempfile in File providers [\#5327](https://github.com/chef/chef/pull/5327) ([lamont-granquist](https://github.com/lamont-granquist)) +- Allow the :delete action for yum\_repository + fix old property support [\#5320](https://github.com/chef/chef/pull/5320) ([tas50](https://github.com/tas50)) + +## [v12.14.60](https://github.com/chef/chef/tree/v12.14.60) (2016-09-09) +[Full Changelog](https://github.com/chef/chef/compare/v12.13.37...v12.14.60) + +**Enhancements:** + +- Only support Solaris 10u11 and newer [\#5264](https://github.com/chef/chef/pull/5264) ([rhass](https://github.com/rhass)) +- Added code to handle deletion of directories on Windows that are symlinks. [\#5234](https://github.com/chef/chef/pull/5234) ([Aliasgar16](https://github.com/Aliasgar16)) +- Readability improvements to options parsing code [\#5289](https://github.com/chef/chef/pull/5289) ([lamont-granquist](https://github.com/lamont-granquist)) +- Add Hash type to launchd:keep\_alive [\#5182](https://github.com/chef/chef/pull/5182) ([erikng](https://github.com/erikng)) +- Added timeout during removing of windows package [\#5250](https://github.com/chef/chef/pull/5250) ([dheerajd-msys](https://github.com/dheerajd-msys)) +- Bump openssl to 1.0.2h [\#5260](https://github.com/chef/chef/pull/5260) ([lamont-granquist](https://github.com/lamont-granquist)) +- Rewrite linux\_user provider check\_lock [\#5248](https://github.com/chef/chef/pull/5248) ([lamont-granquist](https://github.com/lamont-granquist)) +- Allow flagging a resource property as sensitive [\#5185](https://github.com/chef/chef/pull/5185) ([adamleff](https://github.com/adamleff)) +- Rewrite linux useradd provider [\#5243](https://github.com/chef/chef/pull/5243) ([lamont-granquist](https://github.com/lamont-granquist)) +- Add yum_repository resource from the yum cookbook [\#5187](https://github.com/chef/chef/pull/5187) ([thommay](https://github.com/thommay)) +- Verify systemd\_unit file during create [\#5210](https://github.com/chef/chef/pull/5210) ([mal](https://github.com/mal)) +- Add a warning for guard blocks that return a non-empty string [\#5233](https://github.com/chef/chef/pull/5233) ([coderanger](https://github.com/coderanger)) +- Forward package cookbook\_name to underlying remote\_file [\#5128](https://github.com/chef/chef/pull/5128) ([Annih](https://github.com/Annih)) +- Fix "URI.escape is obsolete" warnings [\#5230](https://github.com/chef/chef/pull/5230) ([jkeiser](https://github.com/jkeiser)) +- Remove ruby 2.1 support [\#5220](https://github.com/chef/chef/pull/5220) ([lamont-granquist](https://github.com/lamont-granquist)) +- User provider manage\_home behavior and refactor [\#5122](https://github.com/chef/chef/pull/5122) ([lamont-granquist](https://github.com/lamont-granquist)) +- Fix Style/BlockDelimiters, Style/MultilineBlockLayout and 0.42.0 engine upgrade [\#5218](https://github.com/chef/chef/pull/5218) ([lamont-granquist](https://github.com/lamont-granquist)) +- Switch from Ruby 2.1.9 to Ruby 2.3.1 [\#5190](https://github.com/chef/chef/pull/5190) ([jkeiser](https://github.com/jkeiser)) +- Update to latest chefstyle [\#5217](https://github.com/chef/chef/pull/5217) ([jkeiser](https://github.com/jkeiser)) +- Rubygems memory performance improvement [\#5203](https://github.com/chef/chef/pull/5203) ([lamont-granquist](https://github.com/lamont-granquist)) +- HTTP 1.1 keepalives for cookbook synchronization [\#5151](https://github.com/chef/chef/pull/5151) ([lamont-granquist](https://github.com/lamont-granquist)) + +**Fixed Bugs:** + +- Fixes GH-4955, allowing local gems with remote dependencies [\#5098](https://github.com/chef/chef/pull/5098) ([jyaworski](https://github.com/jyaworski)) +- Hook up the recipe\_file\_loaded event which was defined but not actually called [\#5281](https://github.com/chef/chef/pull/5281) ([coderanger](https://github.com/coderanger)) +- fix gem\_package regression in master [\#5262](https://github.com/chef/chef/pull/5262) ([lamont-granquist](https://github.com/lamont-granquist)) +- Added fix for spaces in profile identifiers [\#5159](https://github.com/chef/chef/pull/5159) ([natewalck](https://github.com/natewalck)) +- Add a hook for compat\_resource [\#5259](https://github.com/chef/chef/pull/5259) ([lamont-granquist](https://github.com/lamont-granquist)) +- Fix flush\_cache issues in yum\_package [\#5258](https://github.com/chef/chef/pull/5258) ([jaymzh](https://github.com/jaymzh)) +- Use symbols instead of strings as keys for systemd user property [\#5241](https://github.com/chef/chef/pull/5241) ([joshuamiller01](https://github.com/joshuamiller01)) +- Use upstart goal state as service status [\#5249](https://github.com/chef/chef/pull/5249) ([evan2645](https://github.com/evan2645)) +- Fix the useradd test filters [\#5236](https://github.com/chef/chef/pull/5236) ([lamont-granquist](https://github.com/lamont-granquist)) +- Fix specify members of group on suse/openbsd/solaris2/hpux [\#5152](https://github.com/chef/chef/pull/5152) ([tas50](https://github.com/tas50)) +- Fix cookbook upload of symlinked cookbooks in Ruby 2.3 on Windows [\#5216](https://github.com/chef/chef/pull/5216) ([jkeiser](https://github.com/jkeiser)) +- Don't use relative\_path\_from on glob results [\#5215](https://github.com/chef/chef/pull/5215) ([jkeiser](https://github.com/jkeiser)) + ## [v12.13.37](https://github.com/chef/chef/tree/v12.13.37) (2016-08-12) [Full Changelog](https://github.com/chef/chef/compare/v12.13.30...v12.13.37) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f9f527381..1f197360f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,58 +1,102 @@ -# Contributing to Chef +# Contributing to Chef Projects -We are glad you want to contribute to Chef! +We're glad you want to contribute to a Chef project! This document will help answer common questions you may have during your first contribution. -We utilize **Github Issues** for issue tracking and contributions. You can contribute in two ways: +## Submitting Issues -1. Reporting an issue or making a feature request [here](#issues). -2. Adding features or fixing bugs yourself and contributing your code to Chef. +Not every contribution comes in the form of code. Submitting, confirming, and triaging issues is an important task for any project. At Chef we use Github to track all project issues. + +If you are familiar with Chef and know the component, that is causing you a problem, you can file an issue in the corresponding Github project. All of our Open Source Software can be found in our [Github organization](https://github.com/chef/). All projects include Github issue templates to help gather information needed for a thorough review. + +We ask you not to submit security concerns via Github. For details on submitting potential security issues please see <https://www.chef.io/security/> + +In addition to Github issues, we also utilize a feedback site that helps our product team track and rank feature requests. If you have a feature request, this is an excellent place to start <https://feedback.chef.io> ## Contribution Process -We have a 3 step process that utilizes **Github Issues**: +We have a 3 step process for contributions: -1. Sign or be added to an existing [Contributor License Agreement (CLA)](https://supermarket.chef.io/become-a-contributor). -2. Create a Github Pull Request. -3. Do [Code Review](#cr) with the **Chef Engineering Team** or **Chef Core Committers** on the pull request. +1. Commit changes to a git branch, making sure to sign-off those changes for the [Developer Certificate of Origin](#developer-certification-of-origin-dco). +2. Create a Github Pull Request for your change, following the instructions in the pull request template. +3. Perform a [Code Review](#code-review-process) with the project maintainers on the pull request. -### Chef Pull Requests +### Pull Request Requirements -Chef is built to last. We strive to ensure high quality throughout the Chef experience. In order to ensure this, we require a couple of things for all pull requests to Chef: +Chef Projects are built to last. We strive to ensure high quality throughout the experience. In order to ensure this, we require that all pull requests to Chef projects meet these specifications: -1. **Tests:** To ensure high quality code and protect against future regressions, we require all the code in Chef to have at least unit test coverage. See the [spec/unit](https://github.com/chef/chef/tree/master/spec/unit) directory for the existing tests and use `bundle exec rake spec` to run them. -2. **Green Travis Run:** We use [Travis CI](https://travis-ci.org/) in order to run our tests continuously on all the pull requests. We require the Travis runs to succeed on every pull request before being merged. +1. **Tests:** To ensure high quality code and protect against future regressions, we require all the code in Chef Projects to have at least unit test coverage. We use [RSpec](http://rspec.info/) for unit testing. +2. **Green CI Tests:** We use [Travis CI](https://travis-ci.org/) and/or [AppVeyor](https://www.appveyor.com/) CI systems to test all pull requests. We require these test runs to succeed on every pull request before being merged. -### Chef Code Review Process +### Code Review Process -The Chef Code Review process happens on Github pull requests. See [this article](https://help.github.com/articles/using-pull-requests) if you're not familiar with Github Pull Requests. +Code review takes place in Github pull requests. See [this article](https://help.github.com/articles/about-pull-requests/) if you're not familiar with Github Pull Requests. -Once you open a pull request, the **Chef Engineering Team** or **Chef Core Committers** will review your code and respond to you with any feedback they might have. The process at this point is as follows: +Once you open a pull request, project maintainers will review your code and respond to your pull request with any feedback they might have. The process at this point is as follows: -1. 2 thumbs-ups are required from the **Chef Engineering Team** or **Chef Core Committers** for all merges. +1. Two thumbs-up (:+1:) are required from project maintainers. See the master maintainers document for Chef projects at <https://github.com/chef/chef/blob/master/MAINTAINERS.md>. 2. When ready, your pull request will be tagged with label `Ready For Merge`. -3. Your patch will be merged into `master` including necessary documentation updates and you will be included in `CHANGELOG.md`. Our goal is to have patches merged in 2 weeks after they are marked to be merged. +3. Your change will be merged into the project's `master` branch and will be noted in the project's `CHANGELOG.md` at the time of release. -If you would like to learn about when your code will be available in a release of Chef, read more about [Chef Release Cycles](#chef-release-cycles). +If you would like to learn about when your code will be available in a release of Chef, read more about [Chef Release Cycles](#release-cycles). -### Contributor License Agreement (CLA) +### Developer Certification of Origin (DCO) Licensing is very important to open source projects. It helps ensure the software continues to be available under the terms that the author desired. Chef uses [the Apache 2.0 license](https://github.com/chef/chef/blob/master/LICENSE) to strike a balance between open contribution and allowing you to use the software however you would like to. -The license tells you what rights you have that are provided by the copyright holder. It is important that the contributor fully understands what rights they are licensing and agrees to them. Sometimes the copyright holder isn't the contributor, such as when the contributor is doing work for a company. +The license tells you what rights you have that are provided by the copyright holder. It is important that the contributor fully understands what rights they are licensing and agrees to them. Sometimes the copyright holder isn't the contributor, such as when the contributor is doing work on behalf of a company. + +To make a good faith effort to ensure these criteria are met, Chef requires the Developer Certificate of Origin (DCO) process to be followed. + +The DCO is an attestation attached to every contribution made by every developer. In the commit message of the contribution, the developer simply adds a Signed-off-by statement and thereby agrees to the DCO, which you can find below or at <http://developercertificate.org/>. + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. +``` + +For more information on the change see the Chef Blog post [Introducing Developer Certificate of Origin](https://blog.chef.io/2016/09/19/introducing-developer-certificate-of-origin/) + +#### DCO Sign-Off Methods -To make a good faith effort to ensure these criteria are met, Chef requires an Individual CLA or a Corporate CLA for contributions. This agreement helps ensure you are aware of the terms of the license you are contributing your copyrighted works under, which helps to prevent the inclusion of works in the projects that the contributor does not hold the rights to share. +The DCO requires a sign-off message in the following format appear on each commit in the pull request: -It only takes a few minutes to complete a CLA, and you retain the copyright to your contribution. +``` +Signed-off-by: Julia Child <juliachild@chef.io> +``` -You can complete our [Individual CLA](https://supermarket.chef.io/icla-signatures/new) online. If you're contributing on behalf of your employer and they retain the copyright for your works, have your employer fill out our [Corporate CLA](https://supermarket.chef.io/ccla-signatures/new) instead. +The DCO text can either be manually added to your commit body, or you can add either **-s** or **--signoff** to your usual git commit commands. If you forget to add the sign-off you can also amend a previous commit with the sign-off by running **git commit –-amend -s**. If you've pushed your changes to Github already you'll need to force push your branch after this with **git push -f**. ### Chef Obvious Fix Policy -Small contributions such as fixing spelling errors, where the content is small enough to not be considered intellectual property, can be submitted by a contributor as a patch, without a CLA. +Small contributions, such as fixing spelling errors, where the content is small enough to not be considered intellectual property, can be submitted without signing the contribution for the DCO. -As a rule of thumb, changes are obvious fixes if they do not introduce any new functionality or creative thinking. As long as the change does not affect functionality, some likely examples include the following: +As a rule of thumb, changes are obvious fixes if they do not introduce any new functionality or creative thinking. Assuming the change does not affect functionality, some common obvious fix examples include the following: - Spelling / grammar fixes - Typo correction, white space and formatting changes @@ -67,36 +111,17 @@ As a rule of thumb, changes are obvious fixes if they do not introduce any new f ``` ------------------------------------------------------------------------ commit 370adb3f82d55d912b0cf9c1d1e99b132a8ed3b5 -Author: danielsdeleo <dan@chef.io> -Date: Wed Sep 18 11:44:40 2013 -0700 +Author: Julia Child <juliachild@chef.io> +Date: Wed Sep 18 11:44:40 2015 -0700 - Fix typo in config file docs. + Fix typo in the README. Obvious fix. ------------------------------------------------------------------------ ``` -## Chef Issue Tracking - -Chef Issue Tracking is handled using Github Issues. - -If you are familiar with Chef and know the component that is causing you a problem or if you have a feature request on a specific component you can file an issue in the corresponding Github project. All of our Open Source Software can be found in our [Github organization](https://github.com/chef/). - -There is also a listing of the various Chef products and where to file issues that can be found in the Chef docs in the [community contributions section](https://docs.chef.io/community_contributions.html#issues-and-bug-reports). - -Otherwise you can file your issue in the [Chef project](https://github.com/chef/chef/issues) and we will make sure it gets filed against the appropriate project. - -### Useful Github Queries - -Contributions go through a review process to improve code quality and avoid regressions. Managing a large number of contributions requires a workflow to provide queues for work such as triage, code review, and merging. A semi-formal process has evolved over the life of the project. Chef maintains this process pending community development and acceptance of an [RFC](https://github.com/chef/chef-rfc). These queries will help track contributions through this process: - -- [Issues that are not assigned to a team](https://github.com/chef/chef/issues?q=is%3Aopen+-label%3AAIX+-label%3ABSD+-label%3Awindows+-label%3A%22Chef+Core%22++-label%3A%22Dev+Tools%22+-label%3AUbuntu+-label%3A%22Enterprise+Linux%22+-label%3A%22Ready+For+Merge%22+-label%3AMac+-label%3ASolaris+) -- [Untriaged Issues](https://github.com/chef/chef/issues?q=is%3Aopen+is%3Aissue+-label%3ABug+-label%3AEnhancement+-label%3A%22Tech+Cleanup%22+-label%3A%22Ready+For+Merge%22) -- [PRs to be Reviewed](https://github.com/chef/chef/labels/Pending%20Maintainer%20Review) -- [Suitable for First Contribution](https://github.com/chef/chef/labels/Easy) - -## Chef Release Cycles +## Release Cycles Our primary shipping vehicle is operating system specific packages that includes all the requirements of Chef. We call these [Omnibus packages](https://github.com/chef/omnibus) @@ -108,7 +133,7 @@ Our version numbering roughly follows [Semantic Versioning](http://semver.org/) - Y is a minor release, which adds both new features and bug fixes - Z is a patch release, which adds just bug fixes -After shipping a release of Chef we bump the `Minor` version by one to start development of the next minor releaae. All merges to master trigger an increment of the `Patch` version, and a build through our internal testing pipeline. We do a `Minor` release approximately every month, which consist of shipping one of the already auto-incremented and tested `Patch` versions. For example after shiping 12.10.24, we incremented Chef to 12.11.0\. From there 18 commits where merged bringing the version to 12.11.18, which we shipped as an omnibus package. +After shipping a release of Chef we bump the `Minor` version by one to start development of the next minor release. All merges to master trigger an increment of the `Patch` version, and a build through our internal testing pipeline. We do a `Minor` release approximately every month, which consist of shipping one of the already auto-incremented and tested `Patch` versions. For example after shiping 12.10.24, we incremented Chef to 12.11.0\. From there 18 commits where merged bringing the version to 12.11.18, which we shipped as an omnibus package. Announcements of releases are made to the [chef mailing list](https://discourse.chef.io/c/chef-release) when they are available. @@ -123,4 +148,4 @@ Also here are some additional pointers to some awesome Chef content: - [Chef Docs](https://docs.chef.io/) - [Learn Chef](https://learn.chef.io/) -- [Chef Inc.](https://www.chef.io/) +- [Chef Website](https://www.chef.io/) @@ -38,7 +38,7 @@ group(:integration) do gem "chefspec" gem "halite" gem "poise" - gem "poise-boiler", git: "https://github.com/poise/poise-boiler" + gem "poise-boiler" gem "knife-windows" gem "foodcritic" diff --git a/Gemfile.lock b/Gemfile.lock index 1224fedd0e..0e9b5d3459 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ GIT remote: https://github.com/chef/chef-server - revision: dea545b10cbe209b89b30e782a58763407ba4526 + revision: 6fde9680c6efdcd0792bec840b7fe7f6fbee790f specs: oc-chef-pedant (2.2.0) - activesupport (~> 3.2) + activesupport (>= 4.2.7.1, < 6.0) erubis (~> 2.7) mixlib-authentication (~> 1.4) mixlib-config (~> 2.0) @@ -23,39 +23,6 @@ GIT rubocop (= 0.42.0) GIT - remote: https://github.com/poise/poise-boiler - revision: 9b8d1393b0dc06af625e3dcc4c0e0a53b2975657 - specs: - poise-boiler (1.11.1.pre) - bundler - chefspec (~> 5.0) - codeclimate-test-reporter (~> 0.4) - codecov (~> 0.0, >= 0.0.2) - foodcritic (~> 7.0) - fuubar (~> 2.0) - git (~> 1.2) - halite (~> 1.2) - kitchen-docker (>= 2.6.0.rc.0) - kitchen-ec2 (~> 1.0) - kitchen-sync (~> 2.1) - kitchen-vagrant - mixlib-shellout (>= 1.4, < 3.0) - poise-profiler (~> 1.0) - pry - pry-byebug - rake (>= 10.4, < 12.0) - rspec (~> 3.2) - rspec-its (~> 1.2) - simplecov (~> 0.9) - test-kitchen (~> 1.7, >= 1.7.1) - travis (~> 1.8, >= 1.8.1) - vagrant-wrapper - winrm (~> 2.0) - winrm-fs (~> 1.0) - yard (~> 0.8) - yard-classmethods (~> 1.0) - -GIT remote: https://github.com/rubysec/bundler-audit.git revision: b7123d7b294f244165d9469f22b37a559e235fc2 specs: @@ -66,10 +33,10 @@ GIT PATH remote: . specs: - chef (12.14.60) + chef (12.15.14) addressable bundler (>= 1.10) - chef-config (= 12.14.60) + chef-config (= 12.15.14) chef-zero (>= 4.8) diff-lcs (~> 1.2, >= 1.2.4) erubis (~> 2.7) @@ -95,10 +62,10 @@ PATH specinfra (~> 2.10) syslog-logger (~> 1.6) uuidtools (~> 2.1.5) - chef (12.14.60-universal-mingw32) + chef (12.15.14-universal-mingw32) addressable bundler (>= 1.10) - chef-config (= 12.14.60) + chef-config (= 12.15.14) chef-zero (>= 4.8) diff-lcs (~> 1.2, >= 1.2.4) erubis (~> 2.7) @@ -139,7 +106,7 @@ PATH PATH remote: chef-config specs: - chef-config (12.14.60) + chef-config (12.15.14) addressable fuzzyurl mixlib-config (~> 2.0) @@ -148,20 +115,22 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (3.2.22.4) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) + activesupport (5.0.0.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) addressable (2.4.0) appbundler (0.9.0) mixlib-cli (~> 1.4) - artifactory (2.3.3) + artifactory (2.5.0) ast (2.3.0) - aws-sdk (2.5.10) - aws-sdk-resources (= 2.5.10) - aws-sdk-core (2.5.10) + aws-sdk (2.6.5) + aws-sdk-resources (= 2.6.5) + aws-sdk-core (2.6.5) jmespath (~> 1.0) - aws-sdk-resources (2.5.10) - aws-sdk-core (= 2.5.10) + aws-sdk-resources (2.6.5) + aws-sdk-core (= 2.6.5) aws-sdk-v1 (1.66.0) json (~> 1.4) nokogiri (>= 1.4.4) @@ -169,14 +138,14 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) - byebug (9.0.5) + byebug (9.0.6) chef-api (0.7.0) logify (~> 0.1) mime-types - chef-provisioning (2.0.1) + chef-provisioning (2.0.2) cheffish (~> 4.0) inifile (>= 2.0.2) - mixlib-install (~> 1.0) + mixlib-install (>= 1.0, < 3.0) net-scp (~> 1.0) net-ssh (>= 2.9, < 4.0) net-ssh-gateway (~> 1.2.0) @@ -198,7 +167,7 @@ GEM cheffish (4.0.0) chef-zero (~> 5.0) net-ssh - chefspec (5.0.0) + chefspec (5.2.0) chef (>= 12.0) fauxhai (~> 3.6) rspec (~> 3.0) @@ -209,7 +178,7 @@ GEM simplecov url coderay (1.1.1) - colorize (0.8.1) + concurrent-ruby (1.0.2) cucumber (2.4.0) builder (>= 2.1.2) cucumber-core (~> 1.5.0) @@ -229,14 +198,14 @@ GEM domain_name (0.5.20160826) unf (>= 0.0.5, < 1.0.0) erubis (2.7.0) - ethon (0.9.0) + ethon (0.9.1) ffi (>= 1.3.0) - excon (0.52.0) + excon (0.53.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) faraday_middleware (0.10.0) faraday (>= 0.7.4, < 0.10) - fauxhai (3.8.0) + fauxhai (3.9.0) net-ssh ffi (1.9.14) ffi (1.9.14-x86-mingw32) @@ -244,7 +213,7 @@ GEM ffi ffi-yajl (2.3.0) libyajl2 (~> 1.2) - foodcritic (7.1.0) + foodcritic (8.0.0) cucumber-core (>= 1.3) erubis nokogiri (>= 1.5, < 2.0) @@ -271,9 +240,9 @@ GEM faraday (~> 0.8, < 0.10) hashie (>= 3.4) oauth2 (~> 1.0) - github_changelog_generator (1.13.1) - colorize (~> 0.7) - github_api (~> 0.12) + github_changelog_generator (1.13.2) + github_api (>= 0.14) + rainbow (>= 2.1) rake (>= 10.0) gssapi (1.2.0) ffi (>= 1.0.1) @@ -284,21 +253,21 @@ GEM chef (~> 12.0) stove (~> 4.0) thor - hashie (3.4.4) + hashie (3.4.6) highline (1.7.8) - http-cookie (1.0.2) + http-cookie (1.0.3) domain_name (~> 0.5) - httpclient (2.8.2.3) + httpclient (2.8.2.4) i18n (0.7.0) inifile (3.0.0) iniparse (1.4.2) ipaddress (0.8.3) jmespath (1.3.1) json (1.8.3) - jwt (1.5.4) - kitchen-docker (2.6.0.rc.0) + jwt (1.5.6) + kitchen-docker (2.6.0) test-kitchen (>= 1.0.0) - kitchen-ec2 (1.1.0) + kitchen-ec2 (1.2.0) aws-sdk (~> 2) excon multi_json @@ -324,13 +293,14 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) + minitest (5.9.1) mixlib-archive (0.2.0) mixlib-log mixlib-authentication (1.4.1) mixlib-log mixlib-cli (1.7.0) mixlib-config (2.2.4) - mixlib-install (1.1.0) + mixlib-install (2.0.3) artifactory mixlib-shellout mixlib-versioning @@ -386,12 +356,40 @@ GEM plist (~> 3.1) systemu (~> 2.6.4) wmi-lite (~> 1.0) - parser (2.3.1.2) + parser (2.3.1.4) ast (~> 2.2) pkg-config (1.1.7) plist (3.2.0) poise (2.7.1) halite (~> 1.0) + poise-boiler (1.13.0) + bundler + chefspec (~> 5.0) + codeclimate-test-reporter (~> 0.4) + codecov (~> 0.0, >= 0.0.2) + foodcritic (~> 8.0) + fuubar (~> 2.0) + git (~> 1.2) + halite (~> 1.2) + kitchen-docker (>= 2.6.0.rc.0) + kitchen-ec2 (~> 1.0) + kitchen-sync (~> 2.1) + kitchen-vagrant + mixlib-shellout (>= 1.4, < 3.0) + poise-profiler (~> 1.0) + pry + pry-byebug + rake (>= 10.4, < 12.0) + rspec (~> 3.2) + rspec-its (~> 1.2) + simplecov (~> 0.9) + test-kitchen (~> 1.7, >= 1.7.1) + travis (~> 1.8, >= 1.8.1) + vagrant-wrapper + winrm (~> 2.0) + winrm-fs (~> 1.0) + yard (~> 0.8) + yard-classmethods (~> 1.0) poise-profiler (1.0.1) halite (~> 1.0) polyglot (0.3.5) @@ -415,7 +413,7 @@ GEM websocket (~> 1.0) rack (2.0.1) rainbow (2.1.0) - rake (11.2.2) + rake (11.3.0) rb-readline (0.5.3) rest-client (2.0.0) http-cookie (>= 1.0.2, < 2.0) @@ -431,7 +429,7 @@ GEM rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) rspec-mocks (~> 3.5.0) - rspec-core (3.5.3) + rspec-core (3.5.4) rspec-support (~> 3.5.0) rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) @@ -457,7 +455,7 @@ GEM ruby-prof (0.16.2) ruby-progressbar (1.8.1) ruby-shadow (2.5.0) - rubyntlm (0.6.0) + rubyntlm (0.6.1) rubyzip (1.2.0) rufus-lru (1.1.0) safe_yaml (1.0.4) @@ -476,7 +474,7 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) - specinfra (2.61.3) + specinfra (2.63.1) net-scp net-ssh (>= 2.7, < 4.0) net-telnet @@ -486,8 +484,8 @@ GEM logify (~> 0.2) syslog-logger (1.6.8) systemu (2.6.5) - test-kitchen (1.12.0) - mixlib-install (~> 1.0, >= 1.0.4) + test-kitchen (1.13.2) + mixlib-install (>= 1.2, < 3.0) mixlib-shellout (>= 1.2, < 3.0) net-scp (~> 1.1) net-ssh (>= 2.9, < 4.0) @@ -510,6 +508,8 @@ GEM polyglot (~> 0.3) typhoeus (0.8.0) ethon (>= 0.8.0) + tzinfo (1.2.2) + thread_safe (~> 0.1) ubuntu_ami (0.4.1) unf (0.1.4) unf_ext @@ -540,7 +540,7 @@ GEM ffi-win32-extensions windows-api (0.4.4) win32-api (>= 1.4.5) - winrm (2.0.1) + winrm (2.0.3) builder (>= 2.1.2) erubis (~> 2.7) gssapi (~> 1.2) @@ -548,8 +548,8 @@ GEM httpclient (~> 2.2, >= 2.2.0.2) logging (>= 1.6.1, < 3.0) nori (~> 2.0) - rubyntlm (~> 0.6.0) - winrm-elevated (1.0.0) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-elevated (1.0.1) winrm (~> 2.0) winrm-fs (~> 1.0) winrm-fs (1.0.0) @@ -590,7 +590,7 @@ DEPENDENCIES oc-chef-pedant! octokit poise - poise-boiler! + poise-boiler pry pry-byebug pry-remote @@ -5,8 +5,8 @@ Want to try Chef? Get started with [learnchef](https://learn.chef.io) -* Documentation: [http://docs.chef.io](http://docs.chef.io) -* Source: [http://github.com/chef/chef/tree/master](http://github.com/chef/chef/tree/master) +* Documentation: [https://docs.chef.io](https://docs.chef.io) +* Source: [https://github.com/chef/chef/tree/master](https://github.com/chef/chef/tree/master) * Tickets/Issues: [https://github.com/chef/chef/issues](https://github.com/chef/chef/issues) * Slack: [Chef Community Slack](https://community-slack.chef.io/) * Mailing list: [https://discourse.chef.io](https://discourse.chef.io) @@ -18,14 +18,14 @@ This README focuses on developers who want to modify Chef source code. If you just want to use Chef, check out these resources: * [learnchef](https://learn.chef.io): Getting started guide -* [docs.chef.io](http://docs.chef.io): Comprehensive User Docs -* [Installer Downloads](https://www.chef.io/download-chef-client/): Install Chef as a complete package +* [docs.chef.io](https://docs.chef.io): Comprehensive User Docs +* [Installer Downloads](https://downloads.chef.io/chef-client/): Install Chef as a complete package ## Installing From Git **NOTE:** Unless you have a specific reason to install from source (to try a new feature, contribute a patch, or run chef on an OS for which no -package is available), you should head to the [installer page](https://www.chef.io/download-chef-client/) +package is available), you should head to the [downloads page](https://downloads.chef.io/chef-client/) to get a prebuilt package. ### Prerequisites @@ -36,7 +36,7 @@ Install these via your platform's preferred method (`apt`, `yum`, `ports`, * git * C compiler, header files, etc. On Ubuntu/Debian, use the `build-essential` package. -* ruby 2.1.0 or later +* ruby 2.3.0 or later * rubygems * bundler gem @@ -65,7 +65,7 @@ gem install pkg/chef-VERSION.gem Before working on the code, if you plan to contribute your changes, you need to read the -[Chef Contributions document](http://docs.chef.io/community_contributions.html). +[Chef Contributions document](https://docs.chef.io/community_contributions.html). The general development process is: @@ -279,6 +279,7 @@ Chef - A configuration management system | **Copyright:** | Copyright 2008-2016, Chef Software, Inc. | **License:** | Apache License, Version 2.0 +``` Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -290,3 +291,4 @@ 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. +``` diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 14e30f1f77..b652d7e837 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,33 +1,44 @@ *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.13: - -Highlights for this release: - -- Ohai 8.18 includes a new plugin for gathering available user shells. Additionally for OS X users there is a new hardware plugin that gathers system information, and we’ve added detection of VMware and VirtualBox installations. - -## Updated Dependencies - -- ruby - 2.1.9 (was 2.1.8) - -### Updated Gems - -- chef-zero - 4.8.0 (was 4.7.0) -- cheffish - 2.0.5 (was 2.0.4) -- compat_resource - 12.10.7 (was 12.10.6) -- ffi - 1.9.14 (was 1.9.10) -- ffi-yajl - 2.3.0 (was 2.2.3) -- fuzzyurl - 0.9.0 (was 0.8.0) -- mixlib-cli - 1.7.0 (was 1.6.0) -- mixlib-log - 1.7.0 (was 1.6.0) -- ohai - 8.18.0 (was 8.17.1) -- pry - 0.10.4 (was 0.10.3) -- rspec - 3.5.0 (was 3.4.0) -- rspec-core - 3.5.2 (was 3.4.4) -- rspec-expectations - 3.5.0 (was 3.4.0) -- rspec-mocks - 3.5.0 (was 3.4.1) -- rspec-support - 3.5.0 (was 3.4.1) -- simplecov - 0.12.0 (was 0.11.2) -- specinfra - 2.60.3 (was 2.59.4) -- mixlib-archive - 0.2.0 (added to package) +Please see [https://docs.chef.io/release_notes.html](https://docs.chef.io/release_notes.html) for the official Chef release notes.* + +# Chef Client Release Notes 12.14: + +## Highlighted enhancements for this release: + +* Upgraded Ruby version from 2.1.9 to 2.3.1 which adds several performance and functionality enhancements. +* Added a small patch to Ruby 2.3.1 and improvements to the Ohai Network plugin in order to support chef client runs on Windows Nano Server. +* Added the ability to mark a property of a custom resource as "sensitive." This will suppress the property's value when it's used in other outputs, such as messages used by the [Data Collector](https://github.com/chef/chef-rfc/blob/master/rfc077-mode-agnostic-data-collection.md). To use, add `sensitive: true` when definine the property. Example: + + ```ruby + property :db_password, String, sensitive: true + ``` + +* Ported the yum_repository resource from the yum cookbook to core chef. With this change you can create and remove repositories without depending on the yum cookbook. Example: + + ```ruby + yum_repository 'OurCo' do + description 'OurCo yum repository' + mirrorlist 'http://artifacts.ourco.org/mirrorlist?repo=ourco-6&arch=$basearch' + gpgkey 'http://artifacts.ourco.org/pub/yum/RPM-GPG-KEY-OURCO-6' + action :create + end + + yum 'Oldrepo' do + action :delete + end + ``` + +* Support for Solaris releases before 10u11 has been removed +* Upgraded Ohai to 8.20 with new / enhanced plugins. See the [ohai changelog](https://github.com/chef-cookbooks/ohai/blob/master/CHANGELOG.md) + +## Highlighted bug fixes for this release: + +Fixed `chef_gem` for local gems with remote dependencies. A recent chef release introduced a breaking change which added the `--local` argument to `gem installs` for local gems prohibiting remote dependencies from being installed. Users who want to ensure that gem installs remain completely local should add `--local` to the `options` property: + +``` +chef_gem 'my-gem' do + source '/tmp/gems/my-gem.gem' + options '--local' + action :install +end +``` @@ -1 +1 @@ -12.14.60
\ No newline at end of file +12.15.14
\ No newline at end of file diff --git a/acceptance/Gemfile b/acceptance/Gemfile index 83f9f7dcfc..59f232fcd3 100644 --- a/acceptance/Gemfile +++ b/acceptance/Gemfile @@ -11,3 +11,6 @@ gem "kitchen-inspec" gem "test-kitchen" gem "winrm-elevated" gem "berkshelf", "4.3.5" + +# until 2.0.0 is fixed for unstable packages +gem "mixlib-install", "1.2.3" diff --git a/acceptance/Gemfile.lock b/acceptance/Gemfile.lock index 9b28266017..55da7b77a8 100644 --- a/acceptance/Gemfile.lock +++ b/acceptance/Gemfile.lock @@ -10,13 +10,13 @@ GEM remote: https://rubygems.org/ specs: addressable (2.4.0) - artifactory (2.3.3) - aws-sdk (2.5.8) - aws-sdk-resources (= 2.5.8) - aws-sdk-core (2.5.8) + artifactory (2.5.0) + aws-sdk (2.6.5) + aws-sdk-resources (= 2.6.5) + aws-sdk-core (2.6.5) jmespath (~> 1.0) - aws-sdk-resources (2.5.8) - aws-sdk-core (= 2.5.8) + aws-sdk-resources (2.6.5) + aws-sdk-core (= 2.6.5) berkshelf (4.3.5) addressable (~> 2.3, >= 2.3.4) berkshelf-api-client (~> 2.0, >= 2.0.2) @@ -53,18 +53,19 @@ GEM celluloid-io (0.16.2) celluloid (>= 0.16.0) nio4r (>= 1.1.0) - chef-config (12.13.37) + chef-config (12.14.89) + addressable fuzzyurl mixlib-config (~> 2.0) mixlib-shellout (~> 2.0) cleanroom (1.0.0) coderay (1.1.1) diff-lcs (1.2.5) - docker-api (1.31.0) + docker-api (1.32.0) excon (>= 0.38.0) json erubis (2.7.0) - excon (0.52.0) + excon (0.53.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) ffi (1.9.14) @@ -73,14 +74,15 @@ GEM ffi (>= 1.0.1) gyoku (1.3.1) builder (>= 2.1.2) - hashie (3.4.4) + hashie (3.4.6) hitimes (1.2.4) httpclient (2.7.2) - inspec (0.32.0) + inspec (1.0.0) hashie (~> 3.4) json (>= 1.8, < 3.0) method_source (~> 0.8) mixlib-log + parallel (~> 1.9) pry (~> 0) rainbow (~> 2) rspec (~> 3) @@ -88,17 +90,17 @@ GEM rubyzip (~> 1.1) sslshake (~> 1) thor (~> 0.19) - train (>= 0.16.0, < 1.0) + train (>= 0.19.1, < 1.0) jmespath (1.3.1) json (2.0.2) - kitchen-ec2 (1.1.0) + kitchen-ec2 (1.2.0) aws-sdk (~> 2) excon multi_json retryable (~> 2.0) test-kitchen (~> 1.4, >= 1.4.1) - kitchen-inspec (0.15.1) - inspec (>= 0.22.0, < 1.0.0) + kitchen-inspec (0.15.2) + inspec (>= 0.22.0, < 2.0.0) test-kitchen (~> 1.6) kitchen-vagrant (0.20.0) test-kitchen (~> 1.4) @@ -113,7 +115,7 @@ GEM mixlib-authentication (1.4.1) mixlib-log mixlib-config (2.2.4) - mixlib-install (1.1.0) + mixlib-install (1.2.3) artifactory mixlib-shellout mixlib-versioning @@ -132,6 +134,7 @@ GEM nori (2.6.0) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) + parallel (1.9.0) pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -160,7 +163,7 @@ GEM rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) rspec-mocks (~> 3.5.0) - rspec-core (3.5.3) + rspec-core (3.5.4) rspec-support (~> 3.5.0) rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) @@ -172,7 +175,7 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.5.0) rspec-support (3.5.0) - rubyntlm (0.6.0) + rubyntlm (0.6.1) rubyzip (1.2.0) safe_yaml (1.0.4) sawyer (0.7.0) @@ -184,8 +187,8 @@ GEM molinillo (~> 0.4.2) semverse (~> 1.1) sslshake (1.0.12) - test-kitchen (1.12.0) - mixlib-install (~> 1.0, >= 1.0.4) + test-kitchen (1.13.2) + mixlib-install (>= 1.2, < 3.0) mixlib-shellout (>= 1.2, < 3.0) net-scp (~> 1.1) net-ssh (>= 2.9, < 4.0) @@ -195,7 +198,7 @@ GEM thor (0.19.1) timers (4.0.4) hitimes - train (0.19.0) + train (0.20.0) docker-api (~> 1.26) json (>= 1.8, < 3.0) mixlib-shellout (~> 2.0) @@ -208,7 +211,7 @@ GEM hashie (>= 2.0.2, < 4.0.0) windows_chef_zero (2.0.0) test-kitchen (>= 1.2.1) - winrm (2.0.1) + winrm (2.0.3) builder (>= 2.1.2) erubis (~> 2.7) gssapi (~> 1.2) @@ -216,8 +219,8 @@ GEM httpclient (~> 2.2, >= 2.2.0.2) logging (>= 1.6.1, < 3.0) nori (~> 2.0) - rubyntlm (~> 0.6.0) - winrm-elevated (1.0.0) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-elevated (1.0.1) winrm (~> 2.0) winrm-fs (~> 1.0) winrm-fs (1.0.0) @@ -236,6 +239,7 @@ DEPENDENCIES kitchen-ec2 kitchen-inspec kitchen-vagrant + mixlib-install (= 1.2.3) test-kitchen windows_chef_zero winrm-elevated diff --git a/acceptance/README.md b/acceptance/README.md index fa4bab2806..992129bf2b 100644 --- a/acceptance/README.md +++ b/acceptance/README.md @@ -1,15 +1,16 @@ # Acceptance Testing for Chef Client -This folder contains acceptance tests that are required for Chef client -release readiness. + +This folder contains acceptance tests that are required for Chef client release readiness. ## Getting started -The tests use the _chef-acceptance_ gem as the high level framework. -All the gems needed to run these tests can be installed with Bundler. + +The tests use the _chef-acceptance_ gem as the high level framework. All the gems needed to run these tests can be installed with Bundler from this directory. ### Important Note! -Before running chef-acceptance, you *MUST* do the following on your current session: -``` +Before running chef-acceptance, you _MUST_ do the following on your current session: + +```shell export APPBUNDLER_ALLOW_RVM=true ``` @@ -17,14 +18,14 @@ export APPBUNDLER_ALLOW_RVM=true ### Set up for local VM (Vagrant) -If you intend to run the acceptance tests on a local VM, the supported solution is to use Vagrant. -Ensure that Vagrant is installed on the machine that tests will run from, along with a -virtualization driver (E.g.: VirtualBox). +If you intend to run the acceptance tests on a local VM, the supported solution is to use Vagrant. Ensure that Vagrant is installed on the machine that tests will run from, along with a virtualization driver (E.g.: VirtualBox). -Set up the KITCHEN_DRIVER environment variable appropriately (value should be "vagrant"). E.g.: -``` +Set up the KITCHEN_DRIVER environment variable appropriately (value should be "vagrant"). E.g.: + +```shell export KITCHEN_DRIVER=vagrant ``` + Add this to your shell profile or startup script as needed. ### Set up for cloud VM (EC2) @@ -34,44 +35,59 @@ If you intend to run the acceptance tests on a cloud VM, the supported solution The steps you will need to do are: 1. Add your AWS credentials to the machine - e.g., to the ~/.aws/credentials directory. - - The easiest way to do this is to download the aws command line (`brew install awscli` on OS/X) and run `aws configure`. + + - The easiest way to do this is to download the aws command line (`brew install awscli` on OS/X) and run `aws configure`. + 2. Create or import a SSH key to AWS. (If you already have one, you can skip the import/create) - - In the AWS console, click Key Pairs, then Create Key Pair or Import Key Pair. + + - In the AWS console, click Key Pairs, then Create Key Pair or Import Key Pair. + 3. Copy or move the private key file (USERNAME.pem) to the SSH folder (e.g. `~/.ssh/USERNAME.pem`). - - If you Created a key pair in step 2, download the private key and move it to `~/.ssh`. - - If you Importd a key pair in step 2, just ensure your private key is in `~/.ssh` and has the same name as the key pair (`~/.ssh/USERNAME` or `~/.ssh/USERNAME.pem`). + + - If you Created a key pair in step 2, download the private key and move it to `~/.ssh`. + - If you Importd a key pair in step 2, just ensure your private key is in `~/.ssh` and has the same name as the key pair (`~/.ssh/USERNAME` or `~/.ssh/USERNAME.pem`). + 4. Set AWS_SSH_KEY_ID to the SSH key name. - - This is **optional** if your AWS SSH key name is your local username. - - You may want to set this in your shell `.profile`. - ```shell - export AWS_SSH_KEY_ID=name-of-private-key - ``` + - This is **optional** if your AWS SSH key name is your local username. + - You may want to set this in your shell `.profile`. + + ```shell + export AWS_SSH_KEY_ID=name-of-private-key + ``` + 5. Set the private key to only be readable by root - ```shell - chmod 0400 ~/.ssh/USERNAME.pem - ``` + ```shell + chmod 0400 ~/.ssh/USERNAME.pem + ``` + 6. Set up the KITCHEN_DRIVER environment variable appropriately (value should be "ec2"). (This is optional, as ec2 is the default.) E.g.: - ```shell - export KITCHEN_DRIVER=ec2 - ``` - Add this to your shell profile or startup script as needed. + ```shell + export KITCHEN_DRIVER=ec2 + ``` + + Add this to your shell profile or startup script as needed. + 7. **Connect to Chef VPN**. The instances you create will not have public IPs! ## Setting up and running a test suite + To get started, do a bundle install from the acceptance directory: + ```shell chef/acceptance$ bundle install --binstubs ``` To get some basic info and ensure chef-acceptance can be run, do: + ```shell chef/acceptance$ bin/chef-acceptance info ``` To run a particular test suite, do the following: + ```shell chef/acceptance$ bin/chef-acceptance test TEST_SUITE ``` @@ -83,26 +99,20 @@ chef/acceptance$ export KITCHEN_INSTANCES=*-ubuntu-1404 chef/acceptance$ bin/chef-acceptance test cookbook-git ``` -If KITCHEN_INSTANCES is not specified, the default instances are default-ubuntu-1404 and default-windows-windows-2012r2. All selected instances will be run in *parallel* if the driver supports it (ec2 does, vagrant doesn't). +If KITCHEN_INSTANCES is not specified, the default instances are default-ubuntu-1404 and default-windows-windows-2012r2\. All selected instances will be run in _parallel_ if the driver supports it (ec2 does, vagrant doesn't). ## Optional Settings -In addition to the environment settings above, there are a number of -key values that are available to set for changing the way the acceptance -tests are run. +In addition to the environment settings above, there are a number of key values that are available to set for changing the way the acceptance tests are run. ### KITCHEN_CHEF_CHANNEL -Use this setting to specify which channel we will pull the chef build from. -The default is to use the "current" channel, unless the ARTIFACTORY_USERNAME is set -(which normally happens when running under Jenkins), in which case the default is -changed to "unstable". +Use this setting to specify which channel we will pull the chef build from. The default is to use the "current" channel, unless the ARTIFACTORY_USERNAME is set (which normally happens when running under Jenkins), in which case the default is changed to "unstable". ```shell export KITCHEN_CHEF_CHANNEL=name-of-channel ``` - ### KITCHEN_CHEF_VERSION Use this setting to override the version of the Chef client that is installed. The default is to get the latest version in the desired channel. @@ -122,11 +132,6 @@ export ARTIFACTORY_PASSWORD=password ## Future Work -Currently, there is no simple mechanism for chef-acceptance -to build an Omnibus package of the developers local chef -instance and run acceptance tests on it - the only packages -that can be exercised are ones that come from one of the -pipeline channels (unstable, current or stable). +Currently, there is no simple mechanism for chef-acceptance to build an Omnibus package of the developers local chef instance and run acceptance tests on it - the only packages that can be exercised are ones that come from one of the pipeline channels (unstable, current or stable). -This is not an issue when adding acceptance tests for pre-existing functionality (as that functionality is presumed -to already be in a build in one of the pipeline channels). +This is not an issue when adding acceptance tests for pre-existing functionality (as that functionality is presumed to already be in a build in one of the pipeline channels). diff --git a/acceptance/fips/.kitchen.yml b/acceptance/fips/.kitchen.yml index 23280f9142..e78a3289d1 100644 --- a/acceptance/fips/.kitchen.yml +++ b/acceptance/fips/.kitchen.yml @@ -1,6 +1,6 @@ suites: - name: fips-unit-functional - includes: [centos-6, windows-2012r2] + includes: [centos-6] run_list: - name: fips-integration diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index be5ca2099c..f2db54aa17 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -659,6 +659,10 @@ module ChefConfig ENV.key?("CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS") end + # Whether the resource count should be updated for log resource + # on running chef-client + default :count_log_resource_updates, true + # knife configuration data config_context :knife do # XXX: none of these default values are applied to knife (and would create a backcompat diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index 598e702034..00f73a44f6 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.14.60" + VERSION = "12.15.14" end # diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml index 9c5854d923..d73b41368d 100644 --- a/kitchen-tests/.kitchen.travis.yml +++ b/kitchen-tests/.kitchen.travis.yml @@ -62,6 +62,9 @@ platforms: - RUN yum clean all - RUN yum -y install which initscripts net-tools sudo wget - RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers + attributes: + chef_client: + init_style: init - name: centos-7 driver: diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock index 50643c0d50..518aa56fac 100644 --- a/kitchen-tests/Berksfile.lock +++ b/kitchen-tests/Berksfile.lock @@ -3,7 +3,7 @@ DEPENDENCIES path: cookbooks/base php (~> 1.5.0) resolver - git: git://github.com/chef-cookbooks/resolver.git + git: https://github.com/chef-cookbooks/resolver.git revision: 8bf9034dabc47d29a07870e4059c32114f2c820a webapp path: cookbooks/webapp @@ -12,8 +12,8 @@ GRAPH apache2 (3.2.2) apt (4.0.2) compat_resource (>= 12.10) - aws (3.4.1) - ohai (>= 2.1.0) + aws (4.1.1) + ohai (>= 4.0) base (0.1.0) apt (>= 0.0.0) build-essential (>= 0.0.0) @@ -29,30 +29,29 @@ GRAPH sudo (>= 0.0.0) ubuntu (>= 0.0.0) users (>= 0.0.0) - yum-epel (>= 0.0.0) - build-essential (6.0.4) - compat_resource (>= 12.10) + build-essential (7.0.0) + compat_resource (>= 12.14) mingw (>= 1.1) seven_zip (>= 0.0.0) - chef-client (5.0.0) + chef-client (6.0.0) cron (>= 1.7.0) logrotate (>= 1.9.0) windows (>= 1.42.0) chef-sugar (3.4.0) - chef_handler (1.4.0) - chef_hostname (0.4.1) + chef_hostname (0.4.2) compat_resource (>= 0.0.0) - compat_resource (12.10.7) - cron (1.7.6) + compat_resource (12.14.7) + cron (2.0.0) database (2.3.1) aws (>= 0.0.0) mysql (~> 5.0) mysql-chef_gem (~> 0.0) postgresql (>= 1.0.0) xfs (>= 0.0.0) - iis (4.2.0) + iis (5.0.1) windows (>= 1.34.6) - iptables (2.2.0) + iptables (3.0.0) + compat_resource (>= 12.14.3) logrotate (2.1.0) compat_resource (>= 0.0.0) mingw (1.2.4) @@ -67,11 +66,10 @@ GRAPH mysql (>= 0.0.0) nscd (4.1.0) compat_resource (>= 0.0.0) - ntp (2.0.0) - windows (>= 1.38.0) - ohai (4.2.0) - compat_resource (>= 12.10) - openssh (2.0.0) + ntp (3.2.0) + ohai (4.2.2) + compat_resource (>= 12.14) + openssh (2.1.0) iptables (>= 1.0) openssl (4.4.0) chef-sugar (>= 3.1.1) @@ -88,25 +86,23 @@ GRAPH openssl (~> 4.0) resolver (1.3.1) selinux (0.9.0) - seven_zip (2.0.1) + seven_zip (2.0.2) windows (>= 1.2.2) - sudo (2.11.0) - ubuntu (1.2.1) + sudo (3.0.0) + ubuntu (2.0.0) apt (>= 0.0.0) - users (3.0.0) + users (4.0.1) webapp (0.1.0) apache2 (~> 3.2.2) database (~> 2.3.1) mysql (~> 5.6.3) php (~> 1.5.0) - windows (1.44.3) - chef_handler (>= 0.0.0) + windows (2.0.2) xfs (2.0.1) - xml (2.0.0) + xml (3.0.0) build-essential (>= 0.0.0) - chef-sugar (>= 0.0.0) - yum (3.11.0) - yum-epel (0.7.1) - yum (>= 3.6.3) - yum-mysql-community (0.3.0) + yum (4.0.0) + yum-epel (1.0.1) + yum (>= 3.6) + yum-mysql-community (1.0.0) yum (>= 3.2) diff --git a/kitchen-tests/Gemfile.lock b/kitchen-tests/Gemfile.lock index 172bd9e418..f1e544cc08 100644 --- a/kitchen-tests/Gemfile.lock +++ b/kitchen-tests/Gemfile.lock @@ -2,21 +2,19 @@ GEM remote: https://rubygems.org/ specs: addressable (2.4.0) - artifactory (2.3.3) - aws-sdk (2.5.5) - aws-sdk-resources (= 2.5.5) - aws-sdk-core (2.5.5) + artifactory (2.5.0) + aws-sdk (2.6.5) + aws-sdk-resources (= 2.6.5) + aws-sdk-core (2.6.5) jmespath (~> 1.0) - aws-sdk-resources (2.5.5) - aws-sdk-core (= 2.5.5) - berkshelf (4.3.5) + aws-sdk-resources (2.6.5) + aws-sdk-core (= 2.6.5) + berkshelf (5.1.0) addressable (~> 2.3, >= 2.3.4) - berkshelf-api-client (~> 2.0, >= 2.0.2) - buff-config (~> 1.0) - buff-extensions (~> 1.0) - buff-shell_out (~> 0.1) - celluloid (= 0.16.0) - celluloid-io (~> 0.16.1) + berkshelf-api-client (>= 2.0.2, < 4.0) + buff-config (~> 2.0) + buff-extensions (~> 2.0) + buff-shell_out (~> 1.0) cleanroom (~> 1.0) faraday (~> 0.9) httpclient (~> 2.7) @@ -24,39 +22,40 @@ GEM mixlib-archive (~> 0.1) octokit (~> 4.0) retryable (~> 2.0) - ridley (~> 4.5) - solve (~> 2.0) + ridley (~> 5.0) + solve (> 2.0, < 4.0) thor (~> 0.19) - berkshelf-api-client (2.0.2) - faraday (~> 0.9.1) - httpclient (~> 2.7.0) - ridley (~> 4.5) - buff-config (1.0.1) - buff-extensions (~> 1.0) - varia_model (~> 0.4) - buff-extensions (1.0.0) - buff-ignore (1.1.1) - buff-ruby_engine (0.1.0) - buff-shell_out (0.2.0) - buff-ruby_engine (~> 0.1.0) + berkshelf-api-client (3.0.0) + faraday (~> 0.9) + httpclient (~> 2.7) + ridley (>= 4.5, < 6.0) + buff-config (2.0.0) + buff-extensions (~> 2.0) + varia_model (~> 0.6) + buff-extensions (2.0.0) + buff-ignore (1.2.0) + buff-ruby_engine (1.0.0) + buff-shell_out (1.1.0) + buff-ruby_engine (~> 1.0) builder (3.2.2) celluloid (0.16.0) timers (~> 4.0.0) celluloid-io (0.16.2) celluloid (>= 0.16.0) nio4r (>= 1.1.0) - chef-config (12.13.37) + chef-config (12.14.89) + addressable fuzzyurl mixlib-config (~> 2.0) mixlib-shellout (~> 2.0) cleanroom (1.0.0) coderay (1.1.1) diff-lcs (1.2.5) - docker-api (1.31.0) + docker-api (1.32.0) excon (>= 0.38.0) json erubis (2.7.0) - excon (0.52.0) + excon (0.53.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) ffi (1.9.14) @@ -66,15 +65,16 @@ GEM ffi (>= 1.0.1) gyoku (1.3.1) builder (>= 2.1.2) - hashie (3.4.4) + hashie (3.4.6) hitimes (1.2.4) hitimes (1.2.4-x86-mingw32) - httpclient (2.7.2) - inspec (0.31.0) + httpclient (2.8.2.4) + inspec (1.0.0) hashie (~> 3.4) - json (~> 1.8) + json (>= 1.8, < 3.0) method_source (~> 0.8) - molinillo (~> 0) + mixlib-log + parallel (~> 1.9) pry (~> 0) rainbow (~> 2) rspec (~> 3) @@ -82,21 +82,21 @@ GEM rubyzip (~> 1.1) sslshake (~> 1) thor (~> 0.19) - train (>= 0.16.0, < 1.0) + train (>= 0.19.1, < 1.0) jmespath (1.3.1) - json (1.8.3) + json (2.0.2) kitchen-appbundle-updater (0.1.2) - kitchen-dokken (0.0.32) + kitchen-dokken (1.0.0) docker-api (~> 1.29) test-kitchen (~> 1.5) - kitchen-ec2 (1.1.0) + kitchen-ec2 (1.2.0) aws-sdk (~> 2) excon multi_json retryable (~> 2.0) test-kitchen (~> 1.4, >= 1.4.1) - kitchen-inspec (0.15.0) - inspec (>= 0.22.0, < 1.0.0) + kitchen-inspec (0.15.2) + inspec (>= 0.22.0, < 2.0.0) test-kitchen (~> 1.6) kitchen-vagrant (0.20.0) test-kitchen (~> 1.4) @@ -110,8 +110,8 @@ GEM mixlib-log mixlib-authentication (1.4.1) mixlib-log - mixlib-config (2.2.2) - mixlib-install (1.1.0) + mixlib-config (2.2.4) + mixlib-install (2.0.3) artifactory mixlib-shellout mixlib-versioning @@ -121,7 +121,7 @@ GEM win32-process (~> 0.8.2) wmi-lite (~> 1.0) mixlib-versioning (1.1.0) - molinillo (0.4.5) + molinillo (0.5.1) multi_json (1.12.1) multipart-post (2.0.0) net-scp (1.2.1) @@ -133,18 +133,19 @@ GEM nori (2.6.0) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) + parallel (1.9.0) pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) rainbow (2.1.0) retryable (2.0.4) - ridley (4.6.1) + ridley (5.1.0) addressable - buff-config (~> 1.0) - buff-extensions (~> 1.0) - buff-ignore (~> 1.1.1) - buff-shell_out (~> 0.1) + buff-config (~> 2.0) + buff-extensions (~> 2.0) + buff-ignore (~> 1.2) + buff-shell_out (~> 1.0) celluloid (~> 0.16.0) celluloid-io (~> 0.16.1) chef-config (>= 12.5.0) @@ -155,13 +156,13 @@ GEM json (>= 1.7.7) mixlib-authentication (>= 1.3.0) retryable (~> 2.0) - semverse (~> 1.1) - varia_model (~> 0.4.0) + semverse (~> 2.0) + varia_model (~> 0.6) rspec (3.5.0) rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) rspec-mocks (~> 3.5.0) - rspec-core (3.5.2) + rspec-core (3.5.4) rspec-support (~> 3.5.0) rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) @@ -173,20 +174,20 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.5.0) rspec-support (3.5.0) - rubyntlm (0.6.0) + rubyntlm (0.6.1) rubyzip (1.2.0) safe_yaml (1.0.4) sawyer (0.7.0) addressable (>= 2.3.5, < 2.5) faraday (~> 0.8, < 0.10) - semverse (1.2.1) + semverse (2.0.0) slop (3.6.0) - solve (2.0.3) - molinillo (~> 0.4.2) - semverse (~> 1.1) + solve (3.0.1) + molinillo (~> 0.4) + semverse (>= 1.1, < 3.0) sslshake (1.0.12) - test-kitchen (1.11.1) - mixlib-install (~> 1.0, >= 1.0.4) + test-kitchen (1.13.2) + mixlib-install (>= 1.2, < 3.0) mixlib-shellout (>= 1.2, < 3.0) net-scp (~> 1.1) net-ssh (>= 2.9, < 4.0) @@ -196,33 +197,34 @@ GEM thor (0.19.1) timers (4.0.4) hitimes - train (0.17.0) + train (0.20.0) docker-api (~> 1.26) - json (~> 1.8) + json (>= 1.8, < 3.0) mixlib-shellout (~> 2.0) net-scp (~> 1.2) net-ssh (>= 2.9, < 4.0) - winrm (~> 1.6) - winrm-fs (~> 0.3) + winrm (~> 2.0) + winrm-fs (~> 1.0) vagrant-wrapper (2.0.3) - varia_model (0.4.1) - buff-extensions (~> 1.0) + varia_model (0.6.0) + buff-extensions (~> 2.0) hashie (>= 2.0.2, < 4.0.0) win32-process (0.8.3) ffi (>= 1.0.0) - winrm (1.8.1) + winrm (2.0.3) 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) - winrm-fs (0.4.3) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-fs (1.0.0) erubis (~> 2.7) logging (>= 1.6.1, < 3.0) rubyzip (~> 1.1) - winrm (~> 1.5) + winrm (~> 2.0) wmi-lite (1.0.0) PLATFORMS diff --git a/kitchen-tests/cookbooks/base/recipes/default.rb b/kitchen-tests/cookbooks/base/recipes/default.rb index 2499dcb814..397d50c016 100644 --- a/kitchen-tests/cookbooks/base/recipes/default.rb +++ b/kitchen-tests/cookbooks/base/recipes/default.rb @@ -28,7 +28,7 @@ end include_recipe "build-essential" -include_recipe "#{cookbook_name}::packages" +include_recipe "::packages" include_recipe "ntp" @@ -50,3 +50,5 @@ include_recipe "openssh" include_recipe "nscd" include_recipe "logrotate" + +include_recipe "::tests" diff --git a/kitchen-tests/cookbooks/base/recipes/tests.rb b/kitchen-tests/cookbooks/base/recipes/tests.rb new file mode 100644 index 0000000000..9d9d813865 --- /dev/null +++ b/kitchen-tests/cookbooks/base/recipes/tests.rb @@ -0,0 +1,21 @@ +# +# Cookbook Name:: webapp +# Recipe:: default +# +# Copyright (C) 2014 +# + +# +# this file is for random tests to check specific chef-client internal functionality +# + +file "/tmp/chef-test-ümlauts" do + content "testing UTF-8 char in the filename" +end + +# this caught a regression in 12.14.70 before it was released when i +# ran it in lamont-ci, so added the test here so everyone else other than +# me gets coverage for this as well. +file "/tmp/chef-test-\xFDmlaut" do + content "testing illegal UTF-8 char in the filename" +end diff --git a/lib/chef/cookbook/file_system_file_vendor.rb b/lib/chef/cookbook/file_system_file_vendor.rb index 91f1c9f853..8088ed00cd 100644 --- a/lib/chef/cookbook/file_system_file_vendor.rb +++ b/lib/chef/cookbook/file_system_file_vendor.rb @@ -37,20 +37,19 @@ class Chef def initialize(manifest, *repo_paths) @cookbook_name = manifest[:cookbook_name] @repo_paths = repo_paths.flatten - raise ArgumentError, "You must specify at least one repo path" if @repo_paths.empty? + raise ArgumentError, "You must specify at least one repo path" if repo_paths.empty? + end + + def cookbooks + @cookbooks ||= Chef::CookbookLoader.new(repo_paths).load_cookbooks end # Implements abstract base's requirement. It looks in the # Chef::Config.cookbook_path file hierarchy for the requested # file. def get_filename(filename) - location = @repo_paths.inject(nil) do |memo, basepath| - candidate_location = File.join(basepath, @cookbook_name, filename) - memo = candidate_location if File.exist?(candidate_location) - memo - end - raise "File #{filename} does not exist for cookbook #{@cookbook_name}" unless location - + location = File.join(cookbooks[cookbook_name].root_dir, filename) if cookbooks.has_key?(cookbook_name) + raise "File #{filename} does not exist for cookbook #{cookbook_name}" unless location && File.exist?(location) location end diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index ab83da9e55..02f9831d70 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -722,6 +722,14 @@ class Chef end end + def method_missing(method, *args, &block) + if block_given? + super + else + Chef::Log.debug "ignoring method #{method} on cookbook with name #{name}, possible typo or future metadata?" + end + end + private # Helper to match a gem style version (ohai_version/chef_version) against a set of diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index a4d5ff60e2..ea779754e2 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -245,6 +245,10 @@ class Chef class Win32RegBadValueSize < ArgumentError; end class Win32RegTypesMismatch < ArgumentError; end + # incorrect input for registry_key create action throws following error + class RegKeyValuesTypeMissing < ArgumentError; end + class RegKeyValuesDataMissing < ArgumentError; end + class InvalidEnvironmentPath < ArgumentError; end class EnvironmentNotFound < RuntimeError; end diff --git a/lib/chef/file_content_management/tempfile.rb b/lib/chef/file_content_management/tempfile.rb index bba4b34d82..cf59a87996 100644 --- a/lib/chef/file_content_management/tempfile.rb +++ b/lib/chef/file_content_management/tempfile.rb @@ -40,7 +40,8 @@ class Chef tempfile_dirnames.each do |tempfile_dirname| begin - tf = ::Tempfile.open(tempfile_basename, tempfile_dirname) + # preserving the file extension of the target filename should be considered a public API + tf = ::Tempfile.open([tempfile_basename, tempfile_extension], tempfile_dirname) break rescue SystemCallError => e message = "Creating temp file under '#{tempfile_dirname}' failed with: '#{e.message}'" @@ -63,12 +64,21 @@ class Chef # as the arguments to Tempfile.new() consistently. # def tempfile_basename - basename = ::File.basename(@new_resource.name) + basename = ::File.basename(@new_resource.path, tempfile_extension) + # the leading "[.]chef-" here should be considered a public API and should not be changed basename.insert 0, "chef-" basename.insert 0, "." unless Chef::Platform.windows? # dotfile if we're not on windows basename end + # this is similar to File.extname() but greedy about the extension (from the first dot, not the last dot) + def tempfile_extension + # complexity here is due to supporting mangling non-UTF8 strings (e.g. latin-1 filenames with characters that are illegal in UTF-8) + b = File.basename(@new_resource.path) + i = b.index(".") + i.nil? ? "" : b[i..-1] + end + # Returns the possible directories for the tempfile to be created in. def tempfile_dirnames # in why-run mode we need to create a Tempfile to compare against, which we will never diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index c9ecfbf0cc..0dbd02ceb4 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -236,6 +236,20 @@ class Chef OFFICIAL_PLUGINS = %w{ec2 rackspace windows openstack terremark bluebox} class << self + def list_commands(preferred_category = nil) + category_desc = preferred_category ? preferred_category + " " : "" + msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n" + subcommand_loader.list_commands(preferred_category).sort.each do |category, commands| + next if category =~ /deprecated/i + msg "** #{category.upcase} COMMANDS **" + commands.sort.each do |command| + subcommand_loader.load_command(command) + msg subcommands[command].banner if subcommands[command] + end + msg + end + end + private # @api private @@ -270,21 +284,6 @@ class Chef end # @api private - def list_commands(preferred_category = nil) - category_desc = preferred_category ? preferred_category + " " : "" - msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n" - subcommand_loader.list_commands(preferred_category).sort.each do |category, commands| - next if category =~ /deprecated/i - msg "** #{category.upcase} COMMANDS **" - commands.sort.each do |command| - subcommand_loader.load_command(command) - msg subcommands[command].banner if subcommands[command] - end - msg - end - end - - # @api private def reset_config_path! @@chef_config_dir = nil end diff --git a/lib/chef/knife/core/generic_presenter.rb b/lib/chef/knife/core/generic_presenter.rb index f273cb5bca..3f5c0712d0 100644 --- a/lib/chef/knife/core/generic_presenter.rb +++ b/lib/chef/knife/core/generic_presenter.rb @@ -175,23 +175,19 @@ class Chef def extract_nested_value(data, nested_value_spec) nested_value_spec.split(".").each do |attr| - if data.nil? - nil # don't get no method error on nil - # Must check :[] before attr because spec can include - # `keys` - want the key named `keys`, not a list of - # available keys. - elsif data.respond_to?(:[]) && data.has_key?(attr) - data = data[attr] - elsif data.respond_to?(attr.to_sym) - data = data.send(attr.to_sym) - else - data = begin - data.send(attr.to_sym) - rescue NoMethodError - nil - end - end + data = + if data.is_a?(Array) + data[attr.to_i] + elsif data.respond_to?(:[], false) && data.key?(attr) + data[attr] + elsif data.respond_to?(attr.to_sym, false) + # handles -a chef_environment and other things that hang of the node and aren't really attributes + data.public_send(attr.to_sym) + else + nil + end end + # necessary (?) for coercing objects (the run_list object?) to hashes ( !data.kind_of?(Array) && data.respond_to?(:to_hash) ) ? data.to_hash : data end diff --git a/lib/chef/mixin/checksum.rb b/lib/chef/mixin/checksum.rb index f223894c39..2888b205a9 100644 --- a/lib/chef/mixin/checksum.rb +++ b/lib/chef/mixin/checksum.rb @@ -27,6 +27,11 @@ class Chef Chef::Digester.checksum_for_file(file) end + def short_cksum(checksum) + return "none" if checksum.nil? + checksum.slice(0, 6) + end + end end end diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index 95b3b09f7e..a4a07275c0 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -452,9 +452,7 @@ class Chef # def merged_attributes(*path) - # immutablize( - merge_all(path) - # ) + immutablize(merge_all(path)) end def combined_override(*path) diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb index b739ea8490..1bd31bceb0 100644 --- a/lib/chef/node/attribute_collections.rb +++ b/lib/chef/node/attribute_collections.rb @@ -73,6 +73,7 @@ class Chef def initialize(root, data) @root = root super(data) + map! { |e| convert_value(e) } end # For elements like Fixnums, true, nil... @@ -86,6 +87,23 @@ class Chef Array.new(map { |e| safe_dup(e) }) end + private + + def convert_value(value) + case value + when VividMash + value + when AttrArray + value + when Hash + VividMash.new(root, value) + when Array + AttrArray.new(root, value) + else + value + end + end + end # == VividMash @@ -184,6 +202,8 @@ class Chef case value when VividMash value + when AttrArray + value when Hash VividMash.new(root, value) when Array diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb index 9e077c8cbb..9e91b12373 100644 --- a/lib/chef/provider/apt_repository.rb +++ b/lib/chef/provider/apt_repository.rb @@ -153,7 +153,7 @@ class Chef end def install_key_from_uri - key_name = new_resource.key.split(%r{\/}).last + key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_") cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name) type = if new_resource.key.start_with?("http") :remote_file diff --git a/lib/chef/provider/apt_update.rb b/lib/chef/provider/apt_update.rb index 0320e9a83f..baa763df9d 100644 --- a/lib/chef/provider/apt_update.rb +++ b/lib/chef/provider/apt_update.rb @@ -73,7 +73,7 @@ class Chef end declare_resource(:file, "#{APT_CONF_DIR}/15update-stamp") do - content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};" + content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};\n" action :create_if_missing end diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index 7f85085eeb..84bb4d1c94 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -344,7 +344,7 @@ class Chef end def do_validate_content - if new_resource.checksum && tempfile && ( new_resource.checksum != tempfile_checksum ) + if new_resource.checksum && tempfile && ( new_resource.checksum.downcase != tempfile_checksum ) raise Chef::Exceptions::ChecksumMismatch.new(short_cksum(new_resource.checksum), short_cksum(tempfile_checksum)) end @@ -462,11 +462,6 @@ class Chef @tempfile ||= content.tempfile end - def short_cksum(checksum) - return "none" if checksum.nil? - checksum.slice(0, 6) - end - def load_resource_attributes_from_file(resource) if Chef::Platform.windows? # This is a work around for CHEF-3554. diff --git a/lib/chef/provider/group/groupadd.rb b/lib/chef/provider/group/groupadd.rb index bc6b5d0208..162875f9f1 100644 --- a/lib/chef/provider/group/groupadd.rb +++ b/lib/chef/provider/group/groupadd.rb @@ -126,7 +126,8 @@ class Chef def groupadd_options opts = "" - opts << " -r" if @new_resource.system + # Solaris doesn't support system groups. + opts << " -r" if @new_resource.system && !node.platform?("solaris2") opts << " -o" if @new_resource.non_unique opts end diff --git a/lib/chef/provider/log.rb b/lib/chef/provider/log.rb index eef4077c07..567781cb41 100644 --- a/lib/chef/provider/log.rb +++ b/lib/chef/provider/log.rb @@ -45,7 +45,7 @@ class Chef # true:: Always return true def action_write Chef::Log.send(@new_resource.level, @new_resource.message) - @new_resource.updated_by_last_action(true) + @new_resource.updated_by_last_action(true) if Chef::Config[:count_log_resource_updates] end end diff --git a/lib/chef/provider/package/cab.rb b/lib/chef/provider/package/cab.rb new file mode 100644 index 0000000000..4e2054fbc2 --- /dev/null +++ b/lib/chef/provider/package/cab.rb @@ -0,0 +1,150 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2015-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/provider/package" +require "chef/resource/cab_package" +require "chef/mixin/shell_out" + +class Chef + class Provider + class Package + class Cab < Chef::Provider::Package + include Chef::Mixin::ShellOut + + provides :cab_package, os: "windows" + + def load_current_resource + @current_resource = Chef::Resource::CabPackage.new(new_resource.name) + current_resource.source(new_resource.source) + new_resource.version(package_version) + current_resource.version(installed_version) + current_resource + end + + def install_package(name, version) + dism_command("/Add-Package /PackagePath:\"#{@new_resource.source}\"") + end + + def remove_package(name, version) + dism_command("/Remove-Package /PackagePath:\"#{@new_resource.source}\"") + end + + def dism_command(command) + shellout = Mixlib::ShellOut.new("dism.exe /Online #{command} /NoRestart", { :timeout => @new_resource.timeout }) + with_os_architecture(nil) do + shellout.run_command + end + end + + def installed_version + stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout + package_info = parse_dism_get_package_info(stdout) + # e.g. Package_for_KB2975719~31bf3856ad364e35~amd64~~6.3.1.8 + package = split_package_identity(package_info["package_information"]["package_identity"]) + # Search for just the package name to catch a different version being installed + Chef::Log.debug("#{@new_resource} searching for installed package #{package['name']}") + found_packages = installed_packages.select { |p| p["package_identity"] =~ /^#{package['name']}~/ } + if found_packages.length == 0 + nil + elsif found_packages.length == 1 + stdout = dism_command("/Get-PackageInfo /PackageName:\"#{found_packages.first["package_identity"]}\"").stdout + find_version(stdout) + else + # Presuming this won't happen, otherwise we need to handle it + raise Chef::Exceptions::Package, "Found multiple packages installed matching name #{package['name']}, found: #{found_packages.length} matches" + end + end + + def package_version + Chef::Log.debug("#{@new_resource} getting product version for package at #{@new_resource.source}") + stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout + find_version(stdout) + end + + def find_version(stdout) + package_info = parse_dism_get_package_info(stdout) + package = split_package_identity(package_info["package_information"]["package_identity"]) + package["version"] + end + + # returns a hash of package state information given the output of dism /get-packages + # expected keys: package_identity + def parse_dism_get_packages(text) + packages = Array.new + text.each_line do |line| + key, value = line.split(":") if line.start_with?("Package Identity") + unless key.nil? || value.nil? + package = Hash.new + package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp + packages << package + end + end + packages + end + + # returns a hash of package information given the output of dism /get-packageinfo + def parse_dism_get_package_info(text) + package_data = Hash.new + errors = Array.new + in_section = false + section_headers = [ "Package information", "Custom Properties", "Features" ] + text.each_line do |line| + if line =~ /Error: (.*)/ + errors << $1.strip + elsif section_headers.any? { |header| line =~ /^(#{header})/ } + in_section = $1.downcase.tr(" ", "_") + elsif line =~ /(.*) ?: (.*)/ + v = $2 # has to be first or the gsub below replaces this variable + k = $1.downcase.strip.tr(" ", "_") + if in_section + package_data[in_section] = Hash.new unless package_data[in_section] + package_data[in_section][k] = v + else + package_data[k] = v + end + end + end + unless errors.empty? + if errors.include?("0x80070003") || errors.include?("0x80070002") + raise Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified." + elsif errors.include?("740") + raise Chef::Exceptions::Package, "DISM: Error 740: Elevated permissions are required to run DISM." + else + raise Chef::Exceptions::Package, "Unknown errors encountered parsing DISM output: #{errors}" + end + end + package_data + end + + def split_package_identity(identity) + data = Hash.new + data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~") + data + end + + def installed_packages + @packages ||= begin + output = dism_command("/Get-Packages").stdout + packages = parse_dism_get_packages(output) + packages + end + end + end + end + end +end diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb index 187197d143..7b9ae909c0 100644 --- a/lib/chef/provider/package/rubygems.rb +++ b/lib/chef/provider/package/rubygems.rb @@ -536,7 +536,6 @@ class Chef def install_via_gem_command(name, version) if @new_resource.source =~ /\.gem$/i name = @new_resource.source - src = " --local" unless source_is_remote? elsif @new_resource.clear_sources src = " --clear-sources" src << (@new_resource.source && " --source=#{@new_resource.source}" || "") diff --git a/lib/chef/provider/package/windows.rb b/lib/chef/provider/package/windows.rb index 753d3c279e..b11bcf5192 100644 --- a/lib/chef/provider/package/windows.rb +++ b/lib/chef/provider/package/windows.rb @@ -250,7 +250,7 @@ class Chef def validate_content! if new_resource.checksum source_checksum = checksum(source_location) - if new_resource.checksum != source_checksum + if new_resource.checksum.downcase != source_checksum raise Chef::Exceptions::ChecksumMismatch.new(short_cksum(new_resource.checksum), short_cksum(source_checksum)) end end diff --git a/lib/chef/provider/registry_key.rb b/lib/chef/provider/registry_key.rb index e516433ac8..58b0a19586 100644 --- a/lib/chef/provider/registry_key.rb +++ b/lib/chef/provider/registry_key.rb @@ -70,27 +70,51 @@ class Chef end end + def key_missing?(values, name) + values.each do |v| + return true unless v.has_key?(name) + end + false + end + def define_resource_requirements requirements.assert(:create, :create_if_missing, :delete, :delete_key) do |a| a.assertion { registry.hive_exists?(@new_resource.key) } a.failure_message(Chef::Exceptions::Win32RegHiveMissing, "Hive #{@new_resource.key.split("\\").shift} does not exist") end + requirements.assert(:create) do |a| a.assertion { registry.key_exists?(@new_resource.key) } a.whyrun("Key #{@new_resource.key} does not exist. Unless it would have been created before, attempt to modify its values would fail.") end + requirements.assert(:create, :create_if_missing) do |a| - #If keys missing in the path and recursive == false + # If keys missing in the path and recursive == false a.assertion { !registry.keys_missing?(@current_resource.key) || @new_resource.recursive } a.failure_message(Chef::Exceptions::Win32RegNoRecursive, "Intermediate keys missing but recursive is set to false") a.whyrun("Intermediate keys in #{@new_resource.key} do not exist. Unless they would have been created earlier, attempt to modify them would fail.") end + requirements.assert(:delete_key) do |a| - #If key to be deleted has subkeys but recurssive == false + # If key to be deleted has subkeys but recurssive == false a.assertion { !registry.key_exists?(@new_resource.key) || !registry.has_subkeys?(@new_resource.key) || @new_resource.recursive } a.failure_message(Chef::Exceptions::Win32RegNoRecursive, "#{@new_resource.key} has subkeys but recursive is set to false.") a.whyrun("#{@current_resource.key} has subkeys, but recursive is set to false. attempt to delete would fails unless subkeys were deleted prior to this action.") end + + requirements.assert(:create, :create_if_missing) do |a| + # If type key missing in the RegistryKey values hash + a.assertion { !key_missing?(@new_resource.values, :type) } + a.failure_message(Chef::Exceptions::RegKeyValuesTypeMissing, "Missing type key in RegistryKey values hash") + a.whyrun("Type key does not exist. Attempt would fail unless the complete values hash containing all the keys does not exist for registry_key resource's create action.") + end + + requirements.assert(:create, :create_if_missing) do |a| + # If data key missing in the RegistryKey values hash + a.assertion { !key_missing?(@new_resource.values, :data) } + a.failure_message(Chef::Exceptions::RegKeyValuesDataMissing, "Missing data key in RegistryKey values hash") + a.whyrun("Data key does not exist. Attempt would fail unless the complete values hash containing all the keys does not exist for registry_key resource's create action.") + end end def action_create @@ -102,6 +126,9 @@ class Chef @new_resource.unscrubbed_values.each do |value| if @name_hash.has_key?(value[:name].downcase) current_value = @name_hash[value[:name].downcase] + if [:dword, :dword_big_endian, :qword].include? value[:type] + value[:data] = value[:data].to_i + end unless current_value[:type] == value[:type] && current_value[:data] == value[:data] converge_by("set value #{value}") do registry.set_value(@new_resource.key, value) diff --git a/lib/chef/provider/remote_file/content.rb b/lib/chef/provider/remote_file/content.rb index e44096428b..983285307a 100644 --- a/lib/chef/provider/remote_file/content.rb +++ b/lib/chef/provider/remote_file/content.rb @@ -54,7 +54,7 @@ class Chef as_uri(source) end raw_file = grab_file_from_uri(uri) - rescue SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError => e + rescue SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError, Errno::ETIMEDOUT => e Chef::Log.warn("#{@new_resource} cannot be downloaded from #{source}: #{e}") if source = sources.shift Chef::Log.info("#{@new_resource} trying to download from another mirror") diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb index 4aa4cd0aa2..a656fbbf80 100644 --- a/lib/chef/provider/systemd_unit.rb +++ b/lib/chef/provider/systemd_unit.rb @@ -193,7 +193,6 @@ class Chef f.group "root" f.mode "0644" f.content new_resource.to_ini - f.verify systemd_analyze_cmd if systemd_analyze_path end.run_action(action) end @@ -234,14 +233,6 @@ class Chef {} end end - - def systemd_analyze_cmd - @systemd_analyze_cmd ||= "#{systemd_analyze_path} verify %{path}" - end - - def systemd_analyze_path - @systemd_analyze_path ||= which("systemd-analyze") - end end end end diff --git a/lib/chef/provider/user/linux.rb b/lib/chef/provider/user/linux.rb index f09d86e98c..4a2491d806 100644 --- a/lib/chef/provider/user/linux.rb +++ b/lib/chef/provider/user/linux.rb @@ -52,14 +52,14 @@ class Chef opts << "-s" << new_resource.shell if should_set?(:shell) opts << "-u" << new_resource.uid if should_set?(:uid) opts << "-d" << new_resource.home if updating_home? - opts << "-o" if new_resource.non_unique + opts << "-o" if non_unique opts end def usermod_options opts = [] if updating_home? - if new_resource.manage_home + if manage_home opts << "-m" end end @@ -69,7 +69,7 @@ class Chef def useradd_options opts = [] opts << "-r" if new_resource.system - if new_resource.manage_home + if manage_home opts << "-m" else opts << "-M" @@ -79,7 +79,7 @@ class Chef def userdel_options opts = [] - opts << "-r" if new_resource.manage_home + opts << "-r" if manage_home opts << "-f" if new_resource.force opts end @@ -122,6 +122,16 @@ class Chef # FIXME: should probably go on the current_resource @locked end + + def non_unique + # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.non_unique + new_resource.non_unique || new_resource.supports[:non_unique] + end + + def manage_home + # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.manage_home + new_resource.manage_home || new_resource.supports[:manage_home] + end end end end diff --git a/lib/chef/provider/user/solaris.rb b/lib/chef/provider/user/solaris.rb index 8d3df9e68b..04567e6bca 100644 --- a/lib/chef/provider/user/solaris.rb +++ b/lib/chef/provider/user/solaris.rb @@ -73,6 +73,21 @@ class Chef private + # Override the version from {#Useradd} because Solaris doesn't support + # system users and therefore has no `-r` option. This also inverts the + # logic for manage_home as Solaris defaults to no-manage-home and only + # offers `-m`. + # + # @since 12.15 + # @api private + # @see Useradd#useradd_options + # @return [Array<String>] + def useradd_options + opts = [] + opts << "-m" if managing_home_dir? + opts + end + def manage_password if @current_resource.password != @new_resource.password && @new_resource.password Chef::Log.debug("#{@new_resource} setting password to #{@new_resource.password}") diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index affa5ca2c1..596629290b 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -83,6 +83,7 @@ require "chef/provider/package/zypper" require "chef/provider/package/solaris" require "chef/provider/package/smartos" require "chef/provider/package/aix" +require "chef/provider/package/cab" require "chef/provider/service/arch" require "chef/provider/service/freebsd" diff --git a/lib/chef/resource/action_class.rb b/lib/chef/resource/action_class.rb index 89b23499d0..98b4d87ef1 100644 --- a/lib/chef/resource/action_class.rb +++ b/lib/chef/resource/action_class.rb @@ -28,6 +28,10 @@ class Chef "#{new_resource || "<no resource>"} action #{action ? action.inspect : "<no action>"}" end + def whyrun_supported? + true + end + # # If load_current_value! is defined on the resource, use that. # diff --git a/lib/chef/resource/cab_package.rb b/lib/chef/resource/cab_package.rb new file mode 100644 index 0000000000..b7acfb0ec9 --- /dev/null +++ b/lib/chef/resource/cab_package.rb @@ -0,0 +1,44 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/resource/package" +require "chef/mixin/uris" + +class Chef + class Resource + class CabPackage < Chef::Resource::Package + include Chef::Mixin::Uris + + provides :cab_package, os: "windows" + + allowed_actions :install, :remove + + def initialize(name, run_context = nil) + super + @resource_name = :cab_package + end + + property :source, String, + coerce: (proc do |s| + unless s.nil? + uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false) + end + end) + end + end +end diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb index 7088e7613e..207de63778 100644 --- a/lib/chef/resource/file.rb +++ b/lib/chef/resource/file.rb @@ -81,7 +81,7 @@ class Chef end def special_docker_files?(file) - %w{/etc/hosts /etc/hostname /etc/resolv.conf}.include?(Pathname(file).cleanpath.to_path) + %w{/etc/hosts /etc/hostname /etc/resolv.conf}.include?(Pathname(file.scrub).cleanpath.to_path) end end end diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb index d11f826c38..da09b9668b 100644 --- a/lib/chef/resource/registry_key.rb +++ b/lib/chef/resource/registry_key.rb @@ -87,13 +87,13 @@ class Chef @values.each do |v| raise ArgumentError, "Missing name key in RegistryKey values hash" unless v.has_key?(:name) - raise ArgumentError, "Missing type key in RegistryKey values hash" unless v.has_key?(:type) - raise ArgumentError, "Missing data key in RegistryKey values hash" unless v.has_key?(:data) v.each_key do |key| raise ArgumentError, "Bad key #{key} in RegistryKey values hash" unless [:name, :type, :data].include?(key) end raise ArgumentError, "Type of name => #{v[:name]} should be string" unless v[:name].is_a?(String) - raise ArgumentError, "Type of type => #{v[:type]} should be symbol" unless v[:type].is_a?(Symbol) + if v[:type] + raise ArgumentError, "Type of type => #{v[:type]} should be symbol" unless v[:type].is_a?(Symbol) + end end @unscrubbed_values = @values elsif self.instance_variable_defined?(:@values) diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb index a07ce8b24b..06dfe95bd4 100644 --- a/lib/chef/resource/user.rb +++ b/lib/chef/resource/user.rb @@ -155,6 +155,20 @@ class Chef :kind_of => [ TrueClass, FalseClass ] ) end + + def supports(args = {}) + if args.key?(:manage_home) + Chef.log_deprecation "supports { manage_home: #{args[:manage_home]} } on the user resource is deprecated and will be removed in Chef 13, set manage_home: #{args[:manage_home]} instead" + end + if args.key?(:non_unique) + Chef.log_deprecation "supports { non_unique: #{args[:non_unique]} } on the user resource is deprecated and will be removed in Chef 13, set non_unique: #{args[:non_unique]} instead" + end + super + end + + def supports=(args) + supports(args) + end end end end diff --git a/lib/chef/resource/user/linux_user.rb b/lib/chef/resource/user/linux_user.rb index 23d6129373..ec60ac89bf 100644 --- a/lib/chef/resource/user/linux_user.rb +++ b/lib/chef/resource/user/linux_user.rb @@ -29,22 +29,12 @@ class Chef def initialize(name, run_context = nil) super @supports = { - manage_home: true, - non_unique: true, + manage_home: false, + non_unique: false, } @manage_home = false end - def supports(args = {}) - Chef.log_deprecation "setting supports on the linux_user resource is deprecated" - # setting is deliberately disabled - super({}) - end - - def supports=(args) - # setting is deliberately disabled - supports({}) - end end end end diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb index 4b3c6edfb7..b1859361b1 100644 --- a/lib/chef/resource/yum_repository.rb +++ b/lib/chef/resource/yum_repository.rb @@ -29,13 +29,13 @@ class Chef property :cost, String, regex: /^\d+$/ property :clean_headers, [TrueClass, FalseClass], default: false # deprecated property :clean_metadata, [TrueClass, FalseClass], default: true - property :description, String, regex: /.*/, default: "Ye Ole Rpm Repo" + property :description, String, regex: /.*/, default: "Yum Repository" property :enabled, [TrueClass, FalseClass], default: true property :enablegroups, [TrueClass, FalseClass] property :exclude, String, regex: /.*/ property :failovermethod, String, equal_to: %w{priority roundrobin} property :fastestmirror_enabled, [TrueClass, FalseClass] - property :gpgcheck, [TrueClass, FalseClass] + property :gpgcheck, [TrueClass, FalseClass], default: true property :gpgkey, [String, Array], regex: /.*/ property :http_caching, String, equal_to: %w{packages all none} property :include_config, String, regex: /.*/ @@ -66,11 +66,14 @@ class Chef property :sslclientkey, String, regex: /.*/ property :sslverify, [TrueClass, FalseClass] property :timeout, String, regex: /^\d+$/ - property :options, Hash default_action :create - allowed_actions :create, :remove, :make_cache, :add + allowed_actions :create, :remove, :makecache, :add, :delete + + # provide compatibility with the yum cookbook < 3.0 properties + alias_method :url, :baseurl + alias_method :keyurl, :gpgkey end end end diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 2afd47a8f4..9ff772353b 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -95,3 +95,4 @@ require "chef/resource/yum_repository" require "chef/resource/lwrp_base" require "chef/resource/bff_package" require "chef/resource/zypper_package" +require "chef/resource/cab_package" diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb index cad8586ac8..d233d25232 100644 --- a/lib/chef/server_api.rb +++ b/lib/chef/server_api.rb @@ -30,7 +30,7 @@ class Chef def initialize(url = Chef::Config[:chef_server_url], options = {}) options[:client_name] ||= Chef::Config[:node_name] - options[:signing_key_filename] ||= Chef::Config[:client_key] + options[:signing_key_filename] ||= Chef::Config[:client_key] unless options[:raw_key] options[:signing_key_filename] = nil if chef_zero_uri?(url) options[:inflate_json_class] = false super(url, options) diff --git a/lib/chef/util/dsc/local_configuration_manager.rb b/lib/chef/util/dsc/local_configuration_manager.rb index 741c6a5898..d837a16185 100644 --- a/lib/chef/util/dsc/local_configuration_manager.rb +++ b/lib/chef/util/dsc/local_configuration_manager.rb @@ -74,7 +74,7 @@ class Chef::Util::DSC def lcm_command_code(configuration_path, test_only_parameters) <<-EOH -$ProgressPreference = 'SilentlyContinue';start-dscconfiguration -path #{@configuration_path} -wait -erroraction 'continue' -force #{test_only_parameters} +$ProgressPreference = 'SilentlyContinue';start-dscconfiguration -path #{@configuration_path} -wait -erroraction 'stop' -force #{test_only_parameters} EOH end diff --git a/lib/chef/version.rb b/lib/chef/version.rb index 1789bf46ad..bb3cdfe80c 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.14.60" + VERSION = "12.15.14" end # diff --git a/omnibus/Gemfile b/omnibus/Gemfile index aae6a0e9c0..735b371c62 100644 --- a/omnibus/Gemfile +++ b/omnibus/Gemfile @@ -1,12 +1,10 @@ source "https://rubygems.org" gem "omnibus", github: "chef/omnibus", branch: "rhass/COOL-502_with_gcc_investigate" -gem "omnibus-software", github: "chef/omnibus-software", branch: "lcg/ruby23" +gem "omnibus-software", github: "chef/omnibus-software", branch: "shain/ruby_windows_monster" gem "license_scout", github: "chef/license_scout" -# pedump pessimistically pins multipart-post to a version from 2013 which makes -# bundler very unhappy. Remove this when upstream has merged zed-0xff/pedump#6 . -gem "pedump", git: "https://github.com/ksubrama/pedump.git", branch: "patch-1" +gem "pedump" # This development group is installed by default when you run `bundle install`, # but if you are using Omnibus in a CI-based infrastructure, you do not need @@ -17,9 +15,9 @@ group :development do gem "berkshelf", "~> 4.0" # Use Test Kitchen with Vagrant for converging the build environment - gem "test-kitchen", "~> 1.9" + gem "test-kitchen", "~> 1.13" gem "kitchen-vagrant", "~> 0.19.0" - gem "winrm-fs", "~> 0.4.0" + gem "winrm-fs", "~> 1.0" gem "pry" gem "pry-byebug" gem "pry-stack_explorer" diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock index d6d5c48245..a54921cb4b 100644 --- a/omnibus/Gemfile.lock +++ b/omnibus/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: git://github.com/chef/license_scout.git - revision: 6e501d31d3957a95388422595db8fe5937092b15 + revision: 4fd26d99d0617d6336ae372f026c190617800e6b specs: license_scout (0.1.2) ffi-yajl (~> 2.2) @@ -8,8 +8,8 @@ GIT GIT remote: git://github.com/chef/omnibus-software.git - revision: f0f4bb4beab18a9b6adbc0a34bcd2f0caf10be5c - branch: lcg/ruby23 + revision: 4ce91af05b8be7d46feac765d0fc24eb28e62c68 + branch: shain/ruby_windows_monster specs: omnibus-software (4.0.0) chef-sugar (>= 3.4.0) @@ -17,7 +17,7 @@ GIT GIT remote: git://github.com/chef/omnibus.git - revision: 98c9af20a0f79b6ac205613f509b4725eea47f7b + revision: 1b5c7a20da006403d5aac2ddc754e43fb97cb540 branch: rhass/COOL-502_with_gcc_investigate specs: omnibus (5.5.0) @@ -32,30 +32,18 @@ GIT ruby-progressbar (~> 1.7) thor (~> 0.18) -GIT - remote: https://github.com/ksubrama/pedump.git - revision: b4319556e18c80d2cba064ffe57fe0dea549dfe2 - branch: patch-1 - specs: - pedump (0.5.0) - awesome_print - iostruct (>= 0.0.4) - multipart-post (~> 1.2) - progressbar - zhexdump (>= 0.0.2) - GEM remote: https://rubygems.org/ specs: addressable (2.4.0) - artifactory (2.3.3) + artifactory (2.5.0) awesome_print (1.7.0) - aws-sdk (2.5.8) - aws-sdk-resources (= 2.5.8) - aws-sdk-core (2.5.8) + aws-sdk (2.6.5) + aws-sdk-resources (= 2.6.5) + aws-sdk-core (2.6.5) jmespath (~> 1.0) - aws-sdk-resources (2.5.8) - aws-sdk-core (= 2.5.8) + aws-sdk-resources (2.6.5) + aws-sdk-core (= 2.6.5) berkshelf (4.3.5) addressable (~> 2.3, >= 2.3.4) berkshelf-api-client (~> 2.0, >= 2.0.2) @@ -89,13 +77,14 @@ GEM buff-shell_out (0.2.0) buff-ruby_engine (~> 0.1.0) builder (3.2.2) - byebug (9.0.5) + byebug (9.0.6) celluloid (0.16.0) timers (~> 4.0.0) celluloid-io (0.16.2) celluloid (>= 0.16.0) nio4r (>= 1.1.0) - chef-config (12.13.37) + chef-config (12.14.89) + addressable fuzzyurl mixlib-config (~> 2.0) mixlib-shellout (~> 2.0) @@ -115,7 +104,7 @@ GEM ffi (>= 1.0.1) gyoku (1.3.1) builder (>= 2.1.2) - hashie (3.4.4) + hashie (3.4.6) hitimes (1.2.4) hitimes (1.2.4-x86-mingw32) httpclient (2.7.2) @@ -138,7 +127,7 @@ GEM mixlib-log mixlib-cli (1.7.0) mixlib-config (2.2.4) - mixlib-install (1.1.0) + mixlib-install (2.0.3) artifactory mixlib-shellout mixlib-versioning @@ -150,7 +139,7 @@ GEM mixlib-versioning (1.1.0) molinillo (0.4.5) multi_json (1.12.1) - multipart-post (1.2.0) + multipart-post (2.0.0) net-scp (1.2.1) net-ssh (>= 2.6.5) net-ssh (3.2.0) @@ -160,7 +149,7 @@ GEM nori (2.6.0) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) - ohai (8.19.2) + ohai (8.20.0) chef-config (>= 12.5.0.alpha.1, < 13) ffi (~> 1.9) ffi-yajl (~> 2.2) @@ -172,6 +161,12 @@ GEM plist (~> 3.1) systemu (~> 2.6.4) wmi-lite (~> 1.0) + pedump (0.5.2) + awesome_print + iostruct (>= 0.0.4) + multipart-post (~> 2.0.0) + progressbar + zhexdump (>= 0.0.2) plist (3.2.0) progressbar (0.21.0) pry (0.10.4) @@ -204,7 +199,7 @@ GEM semverse (~> 1.1) varia_model (~> 0.4.0) ruby-progressbar (1.8.1) - rubyntlm (0.6.0) + rubyntlm (0.6.1) rubyzip (1.2.0) safe_yaml (1.0.4) sawyer (0.7.0) @@ -216,8 +211,8 @@ GEM molinillo (~> 0.4.2) semverse (~> 1.1) systemu (2.6.5) - test-kitchen (1.12.0) - mixlib-install (~> 1.0, >= 1.0.4) + test-kitchen (1.13.2) + mixlib-install (>= 1.2, < 3.0) mixlib-shellout (>= 1.2, < 3.0) net-scp (~> 1.1) net-ssh (>= 2.9, < 4.0) @@ -232,19 +227,20 @@ GEM hashie (>= 2.0.2, < 4.0.0) win32-process (0.8.3) ffi (>= 1.0.0) - winrm (1.8.1) + winrm (2.0.3) 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) - winrm-fs (0.4.3) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-fs (1.0.0) erubis (~> 2.7) logging (>= 1.6.1, < 3.0) rubyzip (~> 1.1) - winrm (~> 1.5) + winrm (~> 2.0) wmi-lite (1.0.0) zhexdump (0.0.2) @@ -258,12 +254,12 @@ DEPENDENCIES license_scout! omnibus! omnibus-software! - pedump! + pedump pry pry-byebug pry-stack_explorer - test-kitchen (~> 1.9) - winrm-fs (~> 0.4.0) + test-kitchen (~> 1.13) + winrm-fs (~> 1.0) BUNDLED WITH 1.12.5 diff --git a/omnibus/config/software/chef-cleanup.rb b/omnibus/config/software/chef-cleanup.rb new file mode 100644 index 0000000000..302e841699 --- /dev/null +++ b/omnibus/config/software/chef-cleanup.rb @@ -0,0 +1,30 @@ +name "chef-cleanup" +default_version "local_source" + +license :project_license +skip_transitive_dependency_licensing true + +source path: project.files_path + +dependency "chef" + +build do + # This is where we get the definitions below + require_relative "../../files/chef/build-chef" + extend BuildChef + + # Clear the now-unnecessary git caches, cached gems, and git-checked-out gems + block "Delete bundler git cache and git installs" do + gemdir = shellout!("#{gem_bin} environment gemdir", env: env).stdout.chomp + remove_directory "#{gemdir}/cache" + remove_directory "#{gemdir}/bundler" + end + + delete "#{install_dir}/embedded/docs" + delete "#{install_dir}/embedded/share/man" + delete "#{install_dir}/embedded/share/doc" + delete "#{install_dir}/embedded/share/gtk-doc" + delete "#{install_dir}/embedded/ssl/man" + delete "#{install_dir}/embedded/man" + delete "#{install_dir}/embedded/info" +end diff --git a/omnibus/config/software/chef-complete.rb b/omnibus/config/software/chef-complete.rb index 8ca370c832..4e2b9f6ec2 100644 --- a/omnibus/config/software/chef-complete.rb +++ b/omnibus/config/software/chef-complete.rb @@ -5,7 +5,7 @@ skip_transitive_dependency_licensing true dependency "chef" dependency "chef-appbundle" -dependency "chef-remove-docs" +dependency "chef-cleanup" dependency "gem-permissions" dependency "shebang-cleanup" diff --git a/omnibus/config/software/chef-remove-docs.rb b/omnibus/config/software/chef-remove-docs.rb deleted file mode 100644 index 31e2797afd..0000000000 --- a/omnibus/config/software/chef-remove-docs.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2012-2014 Chef Software, Inc. -# -# 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. -# - -name "chef-remove-docs" - -license :project_license -skip_transitive_dependency_licensing true - -build do - # This is where we get the definitions below - require_relative "../../files/chef/build-chef" - extend BuildChef - - delete "#{install_dir}/embedded/docs" - delete "#{install_dir}/embedded/share/man" - delete "#{install_dir}/embedded/share/doc" - delete "#{install_dir}/embedded/share/gtk-doc" - delete "#{install_dir}/embedded/ssl/man" - delete "#{install_dir}/embedded/man" - delete "#{install_dir}/embedded/info" -end diff --git a/omnibus/files/chef/build-chef.rb b/omnibus/files/chef/build-chef.rb index 6ff9ca755a..ba7a84c791 100644 --- a/omnibus/files/chef/build-chef.rb +++ b/omnibus/files/chef/build-chef.rb @@ -123,12 +123,5 @@ module BuildChef # Freeze the location's Gemfile.lock. create_bundle_config(shared_gemfile, frozen: true) - - # Clear the now-unnecessary git caches, cached gems, and git-checked-out gems - block "Delete bundler git cache and git installs" do - gemdir = shellout!("#{gem_bin} environment gemdir", env: env).stdout.chomp - remove_file "#{gemdir}/cache" - remove_file "#{gemdir}/bundler" - end end end diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb index 289d6df1f4..53946131cd 100644 --- a/omnibus_overrides.rb +++ b/omnibus_overrides.rb @@ -1,5 +1,5 @@ # DO NOT EDIT. Generated by "rake dependencies". Edit version_policy.rb instead. -override :rubygems, version: "2.6.6" +override :rubygems, version: "2.6.7" override :bundler, version: "1.12.5" override "libffi", version: "3.2.1" override "libiconv", version: "1.14" @@ -10,10 +10,10 @@ override "libxslt", version: "1.1.29" override "libyaml", version: "0.1.6" override "makedepend", version: "1.0.5" override "ncurses", version: "5.9" -override "openssl", version: "1.0.2h" override "pkg-config-lite", version: "0.28-1" override "ruby", version: "2.3.1" override "ruby-windows-devkit-bash", version: "3.1.23-4-msys-1.0.18" override "util-macros", version: "1.19.0" override "xproto", version: "7.0.28" override "zlib", version: "1.2.8" +override "openssl", version: "1.0.2h" diff --git a/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt b/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt b/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt b/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/functional/knife/cookbook_delete_spec.rb b/spec/functional/knife/cookbook_delete_spec.rb index 99f3309752..7438ef9841 100644 --- a/spec/functional/knife/cookbook_delete_spec.rb +++ b/spec/functional/knife/cookbook_delete_spec.rb @@ -20,86 +20,75 @@ require "spec_helper" require "tiny_server" describe Chef::Knife::CookbookDelete do - before(:each) do - @server = TinyServer::Manager.new - @server.start - end - - after(:each) do - @server.stop + let(:server) { TinyServer::Manager.new } + let(:api) { TinyServer::API.instance } + let(:knife_stdout) { StringIO.new } + let(:knife_stderr) { StringIO.new } + let(:knife) do + knife = Chef::Knife::CookbookDelete.new + allow(knife.ui).to receive(:stdout).and_return(knife_stdout) + allow(knife.ui).to receive(:stderr).and_return(knife_stderr) + knife end before(:each) do - @knife = Chef::Knife::CookbookDelete.new - @api = TinyServer::API.instance - @api.clear + server.start + api.clear Chef::Config[:node_name] = nil Chef::Config[:client_key] = nil Chef::Config[:chef_server_url] = "http://localhost:9000" end - context "when the cookbook doesn't exist" do - let(:log_output) { StringIO.new } + after(:each) do + server.stop + end + context "when the cookbook doesn't exist" do before do - @knife.name_args = %w{no-such-cookbook} - @api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({ "error" => "dear Tim, no. -Sent from my iPad" })) - end - - around do |ex| - old_logger = Chef::Log.logger - old_level = Chef::Log.level - begin - Chef::Log.logger = Logger.new(log_output) - Chef::Log.level = :debug - ex.run - ensure - Chef::Log.logger = old_logger - Chef::Log.level = old_level - end + knife.name_args = %w{no-such-cookbook} + api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({ "error" => "dear Tim, no. -Sent from my iPad" })) end it "logs an error and exits" do - allow(@knife.ui).to receive(:stderr).and_return(log_output) - expect { @knife.run }.to raise_error(SystemExit) - expect(log_output.string).to match(/Cannot find a cookbook named no-such-cookbook to delete/) + expect { knife.run }.to raise_error(SystemExit) + expect(knife_stderr.string).to match(/Cannot find a cookbook named no-such-cookbook to delete/) end end context "when there is only one version of a cookbook" do before do - @knife.name_args = %w{obsolete-cookbook} + knife.name_args = %w{obsolete-cookbook} @cookbook_list = { "obsolete-cookbook" => { "versions" => ["version" => "1.0.0"] } } - @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) + api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "asks for confirmation, then deletes the cookbook" do stdin, stdout = StringIO.new("y\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) cb100_deleted = false - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @knife.run + knife.run expect(stdout.string).to match(/#{Regexp.escape('Do you really want to delete obsolete-cookbook version 1.0.0? (Y/N)')}/) expect(cb100_deleted).to be_truthy end it "asks for confirmation before purging" do - @knife.config[:purge] = true + knife.config[:purge] = true stdin, stdout = StringIO.new("y\ny\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) cb100_deleted = false - @api.delete("/cookbooks/obsolete-cookbook/1.0.0?purge=true", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0?purge=true", 200) { cb100_deleted = true; "[\"true\"]" } - @knife.run + knife.run expect(stdout.string).to match(/#{Regexp.escape('Are you sure you want to purge files')}/) expect(stdout.string).to match(/#{Regexp.escape('Do you really want to delete obsolete-cookbook version 1.0.0? (Y/N)')}/) @@ -111,21 +100,21 @@ describe Chef::Knife::CookbookDelete do context "when there are several versions of a cookbook" do before do - @knife.name_args = %w{obsolete-cookbook} + knife.name_args = %w{obsolete-cookbook} versions = ["1.0.0", "1.1.0", "1.2.0"] with_version = lambda { |version| { "version" => version } } @cookbook_list = { "obsolete-cookbook" => { "versions" => versions.map(&with_version) } } - @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) + api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "deletes all versions of a cookbook when given the '-a' flag" do - @knife.config[:all] = true - @knife.config[:yes] = true + knife.config[:all] = true + knife.config[:yes] = true cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } - @knife.run + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } + knife.run expect(cb100_deleted).to be_truthy expect(cb110_deleted).to be_truthy @@ -134,28 +123,28 @@ describe Chef::Knife::CookbookDelete do it "asks which version to delete and deletes that when not given the -a flag" do cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } stdin, stdout = StringIO.new, StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) stdin << "1\n" stdin.rewind - @knife.run + knife.run expect(cb100_deleted).to be_truthy expect(stdout.string).to match(/Which version\(s\) do you want to delete\?/) end it "deletes all versions of the cookbook when not given the -a flag and the user chooses to delete all" do cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } stdin, stdout = StringIO.new("4\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) - @knife.run + knife.run expect(cb100_deleted).to be_truthy expect(cb110_deleted).to be_truthy diff --git a/spec/functional/resource/group_spec.rb b/spec/functional/resource/group_spec.rb index aa5a29f92c..31f9933546 100644 --- a/spec/functional/resource/group_spec.rb +++ b/spec/functional/resource/group_spec.rb @@ -99,8 +99,12 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte usr end - def create_user(username) - user(username).run_action(:create) if ! windows_domain_user?(username) + def create_user(username, uid = nil) + if ! windows_domain_user?(username) + user_to_create = user(username) + user_to_create.uid(uid) if uid + user_to_create.run_action(:create) + end # TODO: User should exist end @@ -169,8 +173,11 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte describe "when the users exist" do before do + high_uid = 30000 (spec_members).each do |member| - create_user(member) + remove_user(member) + create_user(member, high_uid) + high_uid += 1 end end @@ -296,6 +303,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte group = Chef::Resource::Group.new(group_name, run_context) group.members(included_members) group.excluded_members(excluded_members) + group.gid(30000) unless ohai[:platform_family] == "mac_os_x" group end diff --git a/spec/functional/resource/ifconfig_spec.rb b/spec/functional/resource/ifconfig_spec.rb index a30dcff641..0298dbcf45 100644 --- a/spec/functional/resource/ifconfig_spec.rb +++ b/spec/functional/resource/ifconfig_spec.rb @@ -51,11 +51,17 @@ describe Chef::Resource::Ifconfig, :requires_root, :skip_travis, :external => in end end + def fetch_first_interface_name + shell_out("ifconfig | grep Ethernet | head -1 | cut -d' ' -f1").stdout.strip + end + # **Caution: any updates to core interfaces can be risky. def en0_interface_for_test case ohai[:platform] when "aix" "en0" + when "ubuntu" + fetch_first_interface_name else "eth0" end diff --git a/spec/functional/resource/registry_spec.rb b/spec/functional/resource/registry_spec.rb index e64b6697c5..a7748fa4e7 100644 --- a/spec/functional/resource/registry_spec.rb +++ b/spec/functional/resource/registry_spec.rb @@ -153,6 +153,16 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.data_exists?(reg_child, { :name => "Color", :type => :string, :data => "Orange" })).to eq(true) end + it "does not create the key if it already exists with same value and type but datatype of data differs" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "number", :type => :dword, :data => "12345" }]) + @new_resource.run_action(:create) + + expect(@new_resource).not_to be_updated_by_last_action + expect(@registry.key_exists?(reg_child)).to eq(true) + expect(@registry.data_exists?(reg_child, { :name => "number", :type => :dword, :data => 12344 })).to eq(true) + end + it "creates a value if it does not exist" do @new_resource.key(reg_child) @new_resource.values([{ :name => "Mango", :type => :string, :data => "Yellow" }]) @@ -187,13 +197,37 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.value_exists?(reg_child + '\OpscodeTest', { :name => "Chef", :type => :multi_string, :data => %w{OpscodeOrange Rules} })).to eq(true) end - it "gives error if action create and parent does not exist and recursive is set to false" do + it "raises an error if action create and parent does not exist and recursive is set to false" do @new_resource.key(reg_child + '\Missing1\Missing2') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @new_resource.recursive(false) expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::Win32RegNoRecursive) end + it "raises an error if action create and type key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :data => "my_data" }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "raises an error if action create and data key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesDataMissing) + end + + it "raises an error if action create and only name key present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC" }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "does not raise an error if action create and all keys are present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string, :data => "my_data" }]) + expect { @new_resource.run_action(:create) }.to_not raise_error + end + it "creates missing keys if action create and parent does not exist and recursive is set to true" do @new_resource.key(reg_child + '\Missing1\Missing2') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @@ -260,7 +294,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do Chef::Config[:why_run] = true end - it "does not throw an exception if the keys do not exist but recursive is set to false" do + it "does not raise an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Slitheen\Raxicoricofallapatorius') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @new_resource.recursive(false) @@ -268,6 +302,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) expect(@registry.key_exists?(reg_child + '\Slitheen\Raxicoricofallapatorius')).to eq(false) end + it "does not create key if the action is create" do @new_resource.key(reg_child + '\Slitheen') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @@ -275,6 +310,34 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do @new_resource.run_action(:create) expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) end + + it "does not raise an exception if the action create and type key missing in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :data => "my_data" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and data key missing in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :type => :string }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and only name key present in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and all keys are present in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "my_data" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end end end @@ -320,13 +383,37 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.value_exists?(reg_child + '\Pyrovile', { :name => "Chef", :type => :multi_string, :data => %w{OpscodeOrange Rules} })).to eq(true) end - it "gives error if action create and parent does not exist and recursive is set to false" do + it "raises an error if action create and parent does not exist and recursive is set to false" do @new_resource.key(reg_child + '\Sontaran\Sontar') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @new_resource.recursive(false) expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::Win32RegNoRecursive) end + it "raises an error if action create_if_missing and type key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :data => "my_data" }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "raises an error if action create_if_missing and data key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesDataMissing) + end + + it "raises an error if action create_if_missing and only name key present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC" }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "does not raise an error if action create_if_missing and all keys are present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string, :data => "my_data" }]) + expect { @new_resource.run_action(:create_if_missing) }.to_not raise_error + end + it "creates missing keys if action create and parent does not exist and recursive is set to true" do @new_resource.key(reg_child + '\Sontaran\Sontar') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @@ -371,7 +458,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do Chef::Config[:why_run] = true end - it "does not throw an exception if the keys do not exist but recursive is set to false" do + it "does not raise an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Zygons\Zygor') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @new_resource.recursive(false) @@ -379,6 +466,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) expect(@registry.key_exists?(reg_child + '\Zygons\Zygor')).to eq(false) end + it "does nothing if the action is create_if_missing" do @new_resource.key(reg_child + '\Zygons') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @@ -386,6 +474,34 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do @new_resource.run_action(:create_if_missing) expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) end + + it "does not raise an exception if the action create_if_missing and type key missing in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :data => "my_data" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and data key missing in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :type => :string }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and only name key present in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and all keys are present in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "my_data" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end end end diff --git a/spec/integration/recipes/resource_action_spec.rb b/spec/integration/recipes/resource_action_spec.rb index 0f90ed62f8..60d5831a50 100644 --- a/spec/integration/recipes/resource_action_spec.rb +++ b/spec/integration/recipes/resource_action_spec.rb @@ -9,54 +9,70 @@ module ResourceActionSpec shared_context "ActionJackson" do it "the default action is the first declared action" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + end + EOM expect(ActionJackson.ran_action).to eq :access_recipe_dsl expect(ActionJackson.succeeded).to eq true end + context "when running in whyrun mode" do + before do + Chef::Config[:why_run] = true + end + + it "the default action runs" do + converge <<-EOM, __FILE__, __LINE__ + 1 + #{resource_dsl} "hi" do + foo "foo!" + end + EOM + expect(ActionJackson.ran_action).to eq :access_recipe_dsl + expect(ActionJackson.succeeded).to eq true + end + end + it "the action can access recipe DSL" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_recipe_dsl - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_recipe_dsl + end + EOM expect(ActionJackson.ran_action).to eq :access_recipe_dsl expect(ActionJackson.succeeded).to eq true end it "the action can access attributes" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_attribute - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_attribute + end + EOM expect(ActionJackson.ran_action).to eq :access_attribute expect(ActionJackson.succeeded).to eq "foo!" end it "the action can access public methods" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_method + end + EOM expect(ActionJackson.ran_action).to eq :access_method expect(ActionJackson.succeeded).to eq "foo_public!" end it "the action can access protected methods" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_protected_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_protected_method + end + EOM expect(ActionJackson.ran_action).to eq :access_protected_method expect(ActionJackson.succeeded).to eq "foo_protected!" end @@ -64,39 +80,39 @@ module ResourceActionSpec it "the action cannot access private methods" do expect do converge(<<-EOM, __FILE__, __LINE__ + 1) - #{resource_dsl} "hi" do - foo "foo!" - action :access_private_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_private_method + end + EOM end.to raise_error(NameError) expect(ActionJackson.ran_action).to eq :access_private_method end it "the action cannot access resource instance variables" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_instance_variable - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_instance_variable + end + EOM expect(ActionJackson.ran_action).to eq :access_instance_variable expect(ActionJackson.succeeded).to be_nil end it "the action does not compile until the prior resource has converged" do converge <<-EOM, __FILE__, __LINE__ + 1 - ruby_block "wow" do - block do - ResourceActionSpec::ActionJackson.ruby_block_converged = "ruby_block_converged!" + ruby_block "wow" do + block do + ResourceActionSpec::ActionJackson.ruby_block_converged = "ruby_block_converged!" + end end - end - #{resource_dsl} "hi" do - foo "foo!" - action :access_class_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_class_method + end + EOM expect(ActionJackson.ran_action).to eq :access_class_method expect(ActionJackson.succeeded).to eq "ruby_block_converged!" end @@ -141,7 +157,7 @@ module ResourceActionSpec action :access_recipe_dsl do ActionJackson.ran_action = :access_recipe_dsl - ruby_block "hi there" do + whyrun_safe_ruby_block "hi there" do block do ActionJackson.succeeded = true end diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index bfcb74b45c..e4228a7559 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -113,7 +113,7 @@ EOM ruby_block "sleeping" do block do retries = 200 - while IO.read(Chef::Config[:log_location]) !~ /Chef client [0-9]+ is running, will wait for it to finish and then run./ + while IO.read(Chef::Config[:log_location]) !~ /Chef client .* is running, will wait for it to finish and then run./ sleep 0.1 raise "we ran out of retries" if ( retries -= 1 ) <= 0 end @@ -157,7 +157,7 @@ EOM run_log = File.read(path_to("logs/runs.log")) # second run should have a message which indicates it's waiting for the first run - expect(run_log).to match(/Chef client [0-9]+ is running, will wait for it to finish and then run./) + expect(run_log).to match(/Chef client .* is running, will wait for it to finish and then run./) # both of the runs should succeed expect(run_log.lines.reject { |l| !l.include? "INFO: Chef Run complete in" }.length).to eq(2) diff --git a/spec/unit/cookbook/file_vendor_spec.rb b/spec/unit/cookbook/file_vendor_spec.rb index 139a5932f9..164fbd8177 100644 --- a/spec/unit/cookbook/file_vendor_spec.rb +++ b/spec/unit/cookbook/file_vendor_spec.rb @@ -94,4 +94,19 @@ describe Chef::Cookbook::FileVendor do end + context "when vendoring a cookbook with a name mismatch" do + let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks") } + + # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest + let(:manifest) { { :cookbook_name => "name-mismatch" } } + + before do + file_vendor_class.fetch_from_disk(cookbook_path) + end + + it "retrieves the file from the correct location based on path to the cookbook that conatins the correct name metadata" do + file_vendor = file_vendor_class.create_from_manifest(manifest) + file_vendor.get_filename("metadata.rb") + end + end end diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index 27666eb338..389f02501a 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -948,5 +948,24 @@ describe Chef::Cookbook::Metadata do end end + describe "from_file" do + it "ignores unknown metadata fields in metadata.rb files" do + expect(Chef::Log).to receive(:debug).with(/ignoring method some_spiffy_new_metadata_field/) + Tempfile.open("metadata.rb") do |f| + f.write <<-EOF + some_spiffy_new_metadata_field "stuff its set to" + EOF + f.close + metadata.from_file(f.path) + end + end + end + + describe "from_json" do + it "ignores unknown metadata fields in metdata.json files" do + json = %q{{ "some_spiffy_new_metadata_field": "stuff its set to" }} + metadata.from_json(json) + end + end end end diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb index 940edfec2e..e952a5448a 100644 --- a/spec/unit/exceptions_spec.rb +++ b/spec/unit/exceptions_spec.rb @@ -68,6 +68,8 @@ describe Chef::Exceptions do Chef::Exceptions::EnvironmentNotFound => RuntimeError, Chef::Exceptions::InvalidVersionConstraint => ArgumentError, Chef::Exceptions::IllegalVersionConstraint => NotImplementedError, + Chef::Exceptions::RegKeyValuesTypeMissing => ArgumentError, + Chef::Exceptions::RegKeyValuesDataMissing => ArgumentError, } exception_to_super_class.each do |exception, expected_super_class| diff --git a/spec/unit/file_content_management/tempfile_spec.rb b/spec/unit/file_content_management/tempfile_spec.rb index 4b27fc8cc9..a04ace5f16 100644 --- a/spec/unit/file_content_management/tempfile_spec.rb +++ b/spec/unit/file_content_management/tempfile_spec.rb @@ -19,38 +19,59 @@ require "spec_helper" describe Chef::FileContentManagement::Tempfile do - let(:resource) do - r = Chef::Resource::File.new("new_file") - r.path "/foo/bar/new_file" - r - end - subject { described_class.new(resource) } + def tempfile_object_for_path(path) + r = Chef::Resource::File.new("decorative name that should not matter") + r.path path + Chef::FileContentManagement::Tempfile.new(r) + end describe "#tempfile_basename" do it "should return a dotfile", :unix_only do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_basename)).to eql(".chef-new_file") end it "should return a file", :windows_only do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_basename)).to eql("chef-new_file") end + + it "should strip the extension", :unix_only do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_basename)).to eql(".chef-new_file") + end + + it "should strip the extension", :windows_only do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_basename)).to eql("chef-new_file") + end + end + + describe "#tempfile_extension" do + it "should preserve the file extension" do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_extension)).to eql(".html.erb") + end end describe "#tempfile_dirnames" do it "should select a temp dir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = false expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") expect(subject.send(:tempfile_dirnames)).to eql(%w{ /tmp/dir }) end it "should select the destdir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = true expect(subject.send(:tempfile_dirnames)).to eql(%w{ /foo/bar }) end it "should select the destdir and a temp dir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = :auto expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") expect(subject.send(:tempfile_dirnames)).to eql(%w{ /foo/bar /tmp/dir }) @@ -67,18 +88,27 @@ describe Chef::FileContentManagement::Tempfile do end it "should create a temporary file" do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_open)).to be_a(Tempfile) end + it "should preserve the extension in the tempfile path" do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + tempfile = subject.send(:tempfile_open) + expect(tempfile.path).to match(/chef-new_file.*\.html\.erb$/) + end + it "should pick the destdir preferrentially" do - expect(Tempfile).to receive(:open).with(tempname, "/foo/bar").and_return(tempfile) + subject = tempfile_object_for_path("/foo/bar/new_file") + expect(Tempfile).to receive(:open).with([tempname, ""], "/foo/bar").and_return(tempfile) subject.send(:tempfile_open) end it "should use ENV['TMP'] otherwise" do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") - expect(Tempfile).to receive(:open).with(tempname, "/foo/bar").and_raise(SystemCallError, "foo") - expect(Tempfile).to receive(:open).with(tempname, "/tmp/dir").and_return(tempfile) + expect(Tempfile).to receive(:open).with([tempname, ""], "/foo/bar").and_raise(SystemCallError, "foo") + expect(Tempfile).to receive(:open).with([tempname, ""], "/tmp/dir").and_return(tempfile) subject.send(:tempfile_open) end end diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb index 9f525f22f0..be77fd8501 100644 --- a/spec/unit/knife/core/ui_spec.rb +++ b/spec/unit/knife/core/ui_spec.rb @@ -377,12 +377,33 @@ EOM end it "should return the name attribute" do - allow_any_instance_of(Chef::Node).to receive(:name).and_return("chef.localdomain") input = Chef::Node.new + input.name("chef.localdomain") @ui.config[:attribute] = "name" expect(@ui.format_for_display(input)).to eq( { "chef.localdomain" => { "name" => "chef.localdomain" } }) end + it "should return a 'class' attribute and not the node.class" do + input = Chef::Node.new + input.default["class"] = "classy!" + @ui.config[:attribute] = "class" + expect(@ui.format_for_display(input)).to eq( { nil => { "class" => "classy!" } } ) + end + + it "should return the chef_environment attribute" do + input = Chef::Node.new + input.chef_environment = "production-partner-load-integration-preview-testing" + @ui.config[:attribute] = "chef_environment" + expect(@ui.format_for_display(input)).to eq( { nil => { "chef_environment" => "production-partner-load-integration-preview-testing" } } ) + end + + it "works with arrays" do + input = Chef::Node.new + input.default["array"] = %w{zero one two} + @ui.config[:attribute] = "array.1" + expect(@ui.format_for_display(input)).to eq( { nil => { "array.1" => "one" } } ) + end + it "returns nil when given an attribute path that isn't a name or attribute" do input = { "keys" => { "keys" => "values" }, "hi" => "ho", "id" => "sample-data-bag-item" } non_existing_path = "nope.nada.nothingtoseehere" diff --git a/spec/unit/mixin/checksum_spec.rb b/spec/unit/mixin/checksum_spec.rb index 997dcd523e..801c8820d2 100644 --- a/spec/unit/mixin/checksum_spec.rb +++ b/spec/unit/mixin/checksum_spec.rb @@ -37,4 +37,18 @@ describe Chef::Mixin::Checksum do expect(@checksum_user.checksum(@file)).to eq("09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394") end + describe "short_cksum" do + context "nil provided for checksum" do + it "returns none" do + expect(@checksum_user.short_cksum(nil)).to eq("none") + end + end + + context "non-nil provided for checksum" do + it "returns the short checksum" do + expect(@checksum_user.short_cksum("u7ghbxikk3i9blsimmy2y2ionmxx")).to eq("u7ghbx") + end + end + end + end diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index e40f454c0b..00081a9fd9 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -1171,7 +1171,29 @@ describe Chef::Node::Attribute do Chef::Config[:treat_deprecation_warnings_as_errors] = false expect { @attributes.new_key = "new value" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification) end - end + describe "deeply converting values" do + it "converts values through an array" do + @attributes.default[:foo] = [ { bar: true } ] + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"][0]["bar"]).to be true + end + + it "converts values through nested arrays" do + @attributes.default[:foo] = [ [ { bar: true } ] ] + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0][0].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"][0][0]["bar"]).to be true + end + + it "converts values through nested hashes" do + @attributes.default[:foo] = { baz: { bar: true } } + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"]["baz"].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"]["baz"]["bar"]).to be true + end + end end diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb index 5319ba4a35..206b15ef6c 100644 --- a/spec/unit/node/vivid_mash_spec.rb +++ b/spec/unit/node/vivid_mash_spec.rb @@ -37,6 +37,33 @@ describe Chef::Node::VividMash do expect(root).to receive(:top_level_breadcrumb=).with(key).at_least(:once).and_call_original end + context "#[]=" do + it "deep converts values through arrays" do + allow(root).to receive(:reset_cache) + vivid[:foo] = [ { :bar => true } ] + expect(vivid["foo"].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0].class).to eql(Chef::Node::VividMash) + expect(vivid["foo"][0]["bar"]).to be true + end + + it "deep converts values through nested arrays" do + allow(root).to receive(:reset_cache) + vivid[:foo] = [ [ { :bar => true } ] ] + expect(vivid["foo"].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0][0].class).to eql(Chef::Node::VividMash) + expect(vivid["foo"][0][0]["bar"]).to be true + end + + it "deep converts values through hashes" do + allow(root).to receive(:reset_cache) + vivid[:foo] = { baz: { :bar => true } } + expect(vivid["foo"]).to be_an_instance_of(Chef::Node::VividMash) + expect(vivid["foo"]["baz"]).to be_an_instance_of(Chef::Node::VividMash) + expect(vivid["foo"]["baz"]["bar"]).to be true + end + end + context "#read" do before do # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards diff --git a/spec/unit/provider/group/groupadd_spec.rb b/spec/unit/provider/group/groupadd_spec.rb index 93159dd16e..054d953414 100644 --- a/spec/unit/provider/group/groupadd_spec.rb +++ b/spec/unit/provider/group/groupadd_spec.rb @@ -18,156 +18,175 @@ require "spec_helper" -describe Chef::Provider::Group::Groupadd, "set_options" do - before do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - @new_resource = Chef::Resource::Group.new("aj") - @new_resource.gid(50) - @new_resource.members(%w{root aj}) - @new_resource.system false - @new_resource.non_unique false - @current_resource = Chef::Resource::Group.new("aj") - @current_resource.gid(50) - @current_resource.members(%w{root aj}) - @current_resource.system false - @current_resource.non_unique false - @provider = Chef::Provider::Group::Groupadd.new(@new_resource, @run_context) - @provider.current_resource = @current_resource - end - - field_list = { - :gid => "-g", - } - - field_list.each do |attribute, option| - it "should check for differences in #{attribute} between the current and new resources" do - expect(@new_resource).to receive(attribute) - expect(@current_resource).to receive(attribute) - @provider.set_options +describe Chef::Provider::Group::Groupadd do + let(:node) { Chef::Node.new } + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, {}, events) } + let(:new_resource) do + Chef::Resource::Group.new("aj").tap do |r| + r.gid 50 + r.members %w{root aj} + r.system false + r.non_unique false end - it "should set the option for #{attribute} if the new resources #{attribute} is not null" do - allow(@new_resource).to receive(attribute).and_return("wowaweea") - expect(@provider.set_options).to eql(" #{option} '#{@new_resource.send(attribute)}' #{@new_resource.group_name}") + end + let(:current_resource) do + Chef::Resource::Group.new("aj").tap do |r| + r.gid 50 + r.members %w{root aj} + r.system false + r.non_unique false end end - - it "should combine all the possible options" do - match_string = "" - field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option| - allow(@new_resource).to receive(attribute).and_return("hola") - match_string << " #{option} 'hola'" + let(:provider) do + described_class.new(new_resource, run_context).tap do |p| + p.current_resource = current_resource end - match_string << " aj" - expect(@provider.set_options).to eql(match_string) end - describe "when we want to create a system group" do - it "should not set groupadd_options '-r' when system is false" do - @new_resource.system(false) - expect(@provider.groupadd_options).not_to match(/-r/) + describe "#set_options" do + field_list = { + :gid => "-g", + } + + field_list.each do |attribute, option| + it "should check for differences in #{attribute} between the current and new resources" do + expect(new_resource).to receive(attribute) + expect(current_resource).to receive(attribute) + provider.set_options + end + + it "should set the option for #{attribute} if the new resources #{attribute} is not null" do + allow(new_resource).to receive(attribute).and_return("wowaweea") + expect(provider.set_options).to eql(" #{option} '#{new_resource.send(attribute)}' #{new_resource.group_name}") + end end - it "should set groupadd -r if system is true" do - @new_resource.system(true) - expect(@provider.groupadd_options).to eq(" -r") + it "should combine all the possible options" do + match_string = "" + field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option| + allow(new_resource).to receive(attribute).and_return("hola") + match_string << " #{option} 'hola'" + end + match_string << " aj" + expect(provider.set_options).to eql(match_string) end - end - describe "when we want to create a non_unique gid group" do - it "should not set groupadd_options '-o' when non_unique is false" do - @new_resource.non_unique(false) - expect(@provider.groupadd_options).not_to match(/-o/) + describe "when we want to create a system group" do + it "should not set groupadd_options '-r' when system is false" do + new_resource.system(false) + expect(provider.groupadd_options).not_to match(/-r/) + end + + it "should set groupadd -r if system is true" do + new_resource.system(true) + expect(provider.groupadd_options).to eq(" -r") + end + + context "on Solaris" do + before { node.automatic["platform"] = "solaris2" } + it "should not set groupadd -r if system is true" do + new_resource.system(true) + expect(provider.groupadd_options).not_to match(/-r/) + end + end end - it "should set groupadd -o if non_unique is true" do - @new_resource.non_unique(true) - expect(@provider.groupadd_options).to eq(" -o") - end - end -end + describe "when we want to create a non_unique gid group" do + it "should not set groupadd_options '-o' when non_unique is false" do + new_resource.non_unique(false) + expect(provider.groupadd_options).not_to match(/-o/) + end -describe Chef::Provider::Group::Groupadd, "create_group" do - before do - @node = Chef::Node.new - @new_resource = Chef::Resource::Group.new("aj") - @provider = Chef::Provider::Group::Groupadd.new(@node, @new_resource) - allow(@provider).to receive(:run_command).and_return(true) - allow(@provider).to receive(:set_options).and_return(" monkey") - allow(@provider).to receive(:groupadd_options).and_return("") - allow(@provider).to receive(:modify_group_members).and_return(true) + it "should set groupadd -o if non_unique is true" do + new_resource.non_unique(true) + expect(provider.groupadd_options).to eq(" -o") + end + end end - it "should run groupadd with the return of set_options" do - expect(@provider).to receive(:run_command).with({ :command => "groupadd monkey" }).and_return(true) - @provider.create_group - end + describe "#create_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + allow(provider).to receive(:groupadd_options).and_return("") + allow(provider).to receive(:modify_group_members).and_return(true) + end - it "should modify the group members" do - expect(@provider).to receive(:modify_group_members).and_return(true) - @provider.create_group - end -end + it "should run groupadd with the return of set_options" do + expect(provider).to receive(:run_command).with({ :command => "groupadd monkey" }).and_return(true) + provider.create_group + end -describe Chef::Provider::Group::Groupadd do - before do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - @new_resource = Chef::Resource::Group.new("aj") - @provider = Chef::Provider::Group::Groupadd.new(@new_resource, @run_context) - allow(@provider).to receive(:run_command).and_return(true) - allow(@provider).to receive(:set_options).and_return(" monkey") + it "should modify the group members" do + expect(provider).to receive(:modify_group_members).and_return(true) + provider.create_group + end end - describe "manage group" do + describe "#manage_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end it "should run groupmod with the return of set_options" do - allow(@provider).to receive(:modify_group_members).and_return(true) - expect(@provider).to receive(:run_command).with({ :command => "groupmod monkey" }).and_return(true) - @provider.manage_group + allow(provider).to receive(:modify_group_members).and_return(true) + expect(provider).to receive(:run_command).with({ :command => "groupmod monkey" }).and_return(true) + provider.manage_group end it "should modify the group members" do - expect(@provider).to receive(:modify_group_members).and_return(true) - @provider.manage_group + expect(provider).to receive(:modify_group_members).and_return(true) + provider.manage_group end end - describe "remove_group" do + describe "#remove_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end it "should run groupdel with the new resources group name" do - expect(@provider).to receive(:run_command).with({ :command => "groupdel aj" }).and_return(true) - @provider.remove_group + expect(provider).to receive(:run_command).with({ :command => "groupdel aj" }).and_return(true) + provider.remove_group end end [:add_member, :remove_member, :set_members].each do |m| it "should raise an error when calling #{m}" do - expect { @provider.send(m, [ ]) }.to raise_error(Chef::Exceptions::Group, "you must override #{m} in #{@provider}") + expect { provider.send(m, [ ]) }.to raise_error(Chef::Exceptions::Group, "you must override #{m} in #{provider}") end end - describe "load_current_resource" do + describe "#load_current_resource" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end + before do allow(File).to receive(:exists?).and_return(false) - @provider.define_resource_requirements + provider.define_resource_requirements end + it "should raise an error if the required binary /usr/sbin/groupadd doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end + it "should raise an error if the required binary /usr/sbin/groupmod doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end + it "should raise an error if the required binary /usr/sbin/groupdel doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupdel").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end end diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb index 2e4f9c4e52..ce7b1af55a 100644 --- a/spec/unit/provider/log_spec.rb +++ b/spec/unit/provider/log_spec.rb @@ -72,4 +72,18 @@ describe Chef::Provider::Log::ChefLog do expect(Chef::Log).to receive(:info).with(log_str).and_return(true) provider.run_action(:write) end + + context "when count_log_resource_updates is passed in knife.rb" do + it "updates the resource count if count_log_resource_updates=true" do + Chef::Config[:count_log_resource_updates] = true + expect(new_resource).to receive(:updated_by_last_action) + provider.run_action(:write) + end + + it "doesn't update the resource count if count_log_resource_updates=false" do + Chef::Config[:count_log_resource_updates] = false + expect(new_resource).not_to receive(:updated_by_last_action) + provider.run_action(:write) + end + end end diff --git a/spec/unit/provider/package/cab_spec.rb b/spec/unit/provider/package/cab_spec.rb new file mode 100644 index 0000000000..5e16795aa8 --- /dev/null +++ b/spec/unit/provider/package/cab_spec.rb @@ -0,0 +1,218 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "spec_helper" + +describe Chef::Provider::Package::Cab do + let(:timeout) {} + + let(:new_resource) { Chef::Resource::CabPackage.new("windows_test_pkg") } + + let(:provider) do + node = Chef::Node.new + events = Chef::EventDispatch::Dispatcher.new + run_context = Chef::RunContext.new(node, {}, events) + Chef::Provider::Package::Cab.new(new_resource, run_context) + end + + let(:installed_package_list_stdout) do + <<-EOF +Packages listing: +Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0 +Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0 + EOF + end + + let(:package_version_stdout) do + <<-EOF +Package information: +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +State : Installed +Dependency : Language Pack +The operation completed successfully + EOF + end + + before do + new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab" + installed_package_list_obj = double(stdout: installed_package_list_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj) + package_version_obj = double(stdout: package_version_stdout) + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(package_version_obj) + end + + def allow_package_info(package_path = nil, package_name = nil) + get_package_info_stdout = <<-EOF +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +Package information: +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +Applicable : Yes +Copyright : Microsoft Corporation +Company : Microsoft Corporation +State : Installed +Dependency : Language Pack +The operation completed successfully + EOF + get_package_info_obj = double(stdout: get_package_info_stdout) + if package_path + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{package_path}\"").and_return(get_package_info_obj) + else + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"#{package_name}\"").and_return(get_package_info_obj) + end + end + + def allow_get_packages + get_packages_stdout = <<-EOF +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +Packages listing: + +Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0 +State : Installed +Release Type : Language Pack +Install Time : 2/11/2015 11:33 PM + +Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0 +State : Installed +Release Type : Language Pack +Install Time : 2/11/2015 11:33 PM + +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +State : Installed +Release Type : Feature Pack +Install Time : 11/21/2010 3:40 AM + +The operation completed successfully. + EOF + get_packages_obj = double(stdout: get_packages_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(get_packages_obj) + end + + describe "#load_current_resource" do + it "returns a current_resource" do + expect(provider.load_current_resource).to be_kind_of(Chef::Resource::CabPackage) + end + + it "sets the current_resource.version to nil when the package is not installed" do + provider.load_current_resource + expect(provider.current_resource.version).to eql(nil) + end + + it "sets the new resource package version" do + provider.load_current_resource + expect(provider.new_resource.version).to eql("6.1.3.0") + end + end + + describe "#initialize" do + it "returns the correct class" do + expect(provider).to be_kind_of(Chef::Provider::Package::Cab) + end + end + + describe "#package_version" do + it "returns the new package version" do + allow_package_info(new_resource.source, nil) + expect(provider.package_version).to eql("6.1.3.0") + end + end + + describe "#installed_version" do + it "returns the current installed version of package" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + expect(provider.installed_version).to eql("6.1.3.0") + end + end + + describe "#action_remove" do + it "does nothing when the package is already removed" do + provider.load_current_resource + expect(provider).not_to receive(:remove_package) + provider.run_action(:remove) + expect(new_resource).not_to be_updated_by_last_action + end + + it "removes packages if package is installed" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + provider.load_current_resource + expect(provider.installed_version).not_to eql(nil) + expect(provider).to receive(:remove_package) + provider.run_action(:remove) + expect(new_resource).to be_updated_by_last_action + end + end + + describe "#action_install" do + it "installs package if already not installed" do + provider.load_current_resource + expect(provider.installed_version).to eql(nil) + expect(provider).to receive(:install_package) + provider.run_action(:install) + expect(new_resource).to be_updated_by_last_action + end + + it "does not install package if already installed" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + provider.load_current_resource + expect(provider.installed_version).not_to eql(nil) + expect(provider).not_to receive(:install_package) + provider.run_action(:install) + expect(new_resource).not_to be_updated_by_last_action + end + end + + context "Invalid package source" do + def package_version_stdout + package_version_stdout = <<-EOF + +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +An error occurred trying to open - c:\\temp\\test6.1-KB2664825-v3-x64.cab Error: 0x80070003 +Error: 3 +The system cannot find the path specified. +The DISM log file can be found at C:\\Windows\\Logs\\DISM\\dism.log. + EOF + end + + before do + new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab" + installed_package_list_obj = double(stdout: installed_package_list_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj) + end + + it "raises error for invalid source path or file" do + expect { provider.load_current_resource }.to raise_error(Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified.") + end + end +end diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb index 4934505583..548204df75 100644 --- a/spec/unit/provider/package/rubygems_spec.rb +++ b/spec/unit/provider/package/rubygems_spec.rb @@ -735,10 +735,9 @@ describe Chef::Provider::Package::Rubygems do context "when source is a path" do let(:source) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" } let(:target_version) { ">= 0" } - let(:domain) { " --local" } it "installs the gem by shelling out to gem install" do - expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{source} -q --no-rdoc --no-ri -v \"#{target_version}\"#{domain}", env: nil, timeout: 900) + expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{source} -q --no-rdoc --no-ri -v \"#{target_version}\"", env: nil, timeout: 900) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -747,11 +746,10 @@ describe Chef::Provider::Package::Rubygems do context "when the package is a path and source is nil" do let(:gem_name) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" } let(:target_version) { ">= 0" } - let(:domain) { " --local" } it "installs the gem from file by shelling out to gem install when the package is a path and the source is nil" do expect(new_resource.source).to eq(gem_name) - expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{gem_name} -q --no-rdoc --no-ri -v \"#{target_version}\"#{domain}", env: nil, timeout: 900) + expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{gem_name} -q --no-rdoc --no-ri -v \"#{target_version}\"", env: nil, timeout: 900) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb index e26662ac75..d1d717bdbe 100644 --- a/spec/unit/provider/package/windows_spec.rb +++ b/spec/unit/provider/package/windows_spec.rb @@ -394,4 +394,49 @@ describe Chef::Provider::Package::Windows, :windows_only do end end end + + shared_context "valid checksum" do + context "checksum is valid" do + before do + allow(provider).to receive(:checksum).and_return("jiie00u3bbs92vsbhvgvklb2lasgh20ah") + end + + it "does not raise the checksum mismatch exception" do + expect { provider.send(:validate_content!) }.to_not raise_error + end + end + end + + shared_context "invalid checksum" do + context "checksum is invalid" do + before do + allow(provider).to receive(:checksum).and_return("kiie30u3bbs92vsbhvgvklb2lasgh20ah") + end + + it "raises the checksum mismatch exception" do + expect { provider.send(:validate_content!) }.to raise_error( + Chef::Exceptions::ChecksumMismatch) + end + end + end + + describe "validate_content!" do + before(:each) do + new_resource.checksum("jiie00u3bbs92vsbhvgvklb2lasgh20ah") + end + + context "checksum is in lowercase" do + include_context "valid checksum" + include_context "invalid checksum" + end + + context "checksum is in uppercase" do + before do + new_resource.checksum = new_resource.checksum.upcase + end + + include_context "valid checksum" + include_context "invalid checksum" + end + end end diff --git a/spec/unit/provider/registry_key_spec.rb b/spec/unit/provider/registry_key_spec.rb index 41bc5b33d3..3fb9468f5d 100644 --- a/spec/unit/provider/registry_key_spec.rb +++ b/spec/unit/provider/registry_key_spec.rb @@ -19,23 +19,6 @@ require "spec_helper" shared_examples_for "a registry key" do - before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::RegistryKey.new("windows is fun", @run_context) - @new_resource.key keyname - @new_resource.values( testval1 ) - @new_resource.recursive false - - @provider = Chef::Provider::RegistryKey.new(@new_resource, @run_context) - - allow(@provider).to receive(:running_on_windows!).and_return(true) - @double_registry = double(Chef::Win32::Registry) - allow(@provider).to receive(:registry).and_return(@double_registry) - end - describe "when first created" do end @@ -273,6 +256,23 @@ shared_examples_for "a registry key" do end describe Chef::Provider::RegistryKey do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::RegistryKey.new("windows is fun", @run_context) + @new_resource.key keyname + @new_resource.values( testval1 ) + @new_resource.recursive false + + @provider = Chef::Provider::RegistryKey.new(@new_resource, @run_context) + + allow(@provider).to receive(:running_on_windows!).and_return(true) + @double_registry = double(Chef::Win32::Registry) + allow(@provider).to receive(:registry).and_return(@double_registry) + end + context "when the key data is safe" do let(:keyname) { 'HKLM\Software\Opscode\Testing\Safe' } let(:testval1) { { :name => "one", :type => :string, :data => "1" } } @@ -292,4 +292,116 @@ describe Chef::Provider::RegistryKey do it_should_behave_like "a registry key" end + + describe "action_create" do + context "when key exists and type matches" do + let(:keyname) { 'hklm\\software\\opscode\\testing\\dword' } + let(:dword_passed_as_integer) { { :name => "one", :type => :dword, :data => 12345 } } + let(:testval1) { { :name => "one", :type => :dword, :data => "12345" } } + before do + expect(@double_registry).to receive(:key_exists?).twice.with(keyname).and_return(true) + end + + it "does not make a change for datatype of data value differing" do + expect(@double_registry).to receive(:get_values).with(keyname).and_return( dword_passed_as_integer ) + expect(@double_registry).not_to receive(:set_value) + @provider.load_current_resource + @provider.action_create + end + end + end +end + +describe Chef::Provider::RegistryKey, "key_missing?" do + let(:provider) { Chef::Provider::RegistryKey.new(nil, nil) } + let(:all_keys_present_in_all_hash) do + [ { :name => "input1_value1", :type => :string, :data => "my_value1" }, + { :name => "input1_value2", :type => :string, :data => "my_value2" }, + ] + end + let(:type_key_not_present_in_any_hash) do + [ { :name => "input2_value1", :data => "my_value1" }, + { :name => "input2_value2", :data => "my_value2" }, + ] + end + let(:type_key_not_present_in_some_hash) do + [ { :name => "input3_value1", :data => "my_value1" }, + { :name => "input3_value2", :type => :string, :data => "my_value2" }, + ] + end + let(:data_key_not_present_in_any_hash) do + [ { :name => "input4_value1", :type => :string }, + { :name => "input4_value2", :type => :string }, + ] + end + let(:data_key_not_present_in_some_hash) do + [ { :name => "input5_value1", :type => :string, :data => "my_value1" }, + { :name => "input5_value2", :type => :string }, + ] + end + let(:only_name_key_present_in_all_hash) do + [ { :name => "input6_value1" }, + { :name => "input6_value2" }, + ] + end + + context "type key" do + context "when type key is present in all the values hash of registry_key resource" do + it "returns false" do + response = provider.key_missing?(all_keys_present_in_all_hash, :type) + expect(response).to be == false + end + end + + context "when type key is not present in any of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(type_key_not_present_in_any_hash, :type) + expect(response).to be == true + end + end + + context "when type key is not present only in some of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(type_key_not_present_in_some_hash, :type) + expect(response).to be == true + end + end + + context "when only name key is present in all the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(only_name_key_present_in_all_hash, :type) + expect(response).to be == true + end + end + end + + context "data key" do + context "when data key is present in all the values hash of registry_key resource" do + it "returns false" do + response = provider.key_missing?(all_keys_present_in_all_hash, :data) + expect(response).to be == false + end + end + + context "when data key is not present in any of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(data_key_not_present_in_any_hash, :data) + expect(response).to be == true + end + end + + context "when data key is not present only in some of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(data_key_not_present_in_some_hash, :data) + expect(response).to be == true + end + end + + context "when only name key is present in all the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(only_name_key_present_in_all_hash, :data) + expect(response).to be == true + end + end + end end diff --git a/spec/unit/provider/remote_file/content_spec.rb b/spec/unit/provider/remote_file/content_spec.rb index c6a560b123..db9a75458d 100644 --- a/spec/unit/provider/remote_file/content_spec.rb +++ b/spec/unit/provider/remote_file/content_spec.rb @@ -180,6 +180,7 @@ describe Chef::Provider::RemoteFile::Content do Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError, + Errno::ETIMEDOUT, ].each do |exception| describe "with an exception of #{exception}" do before do diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb index dfaaa377d3..7b8be02f3a 100644 --- a/spec/unit/provider/user/dscl_spec.rb +++ b/spec/unit/provider/user/dscl_spec.rb @@ -219,6 +219,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30" end before do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports({ :manage_home => true }) new_resource.home("/Users/toor") @@ -237,6 +239,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30" end it "moves the users home to the new location if it exists and the target location is different" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports(:manage_home => true) current_home = CHEF_SPEC_DATA + "/old_home_dir" @@ -856,6 +859,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30") describe "when Chef is removing the user" do it "removes the user from the groups and deletes home directory when the resource is configured to manage home" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports({ :manage_home => true }) expect(provider).to receive(:run_dscl).with("list /Groups").and_return("my_group\nyour_group\nreal_group\n") expect(provider).to receive(:run_dscl).with("read /Groups/my_group").and_raise(Chef::Exceptions::DsclCommandFailed) # Empty group diff --git a/spec/unit/provider/user/linux_spec.rb b/spec/unit/provider/user/linux_spec.rb index ac94592859..1c487c0de9 100644 --- a/spec/unit/provider/user/linux_spec.rb +++ b/spec/unit/provider/user/linux_spec.rb @@ -45,20 +45,50 @@ describe Chef::Provider::User::Linux do @current_resource = Chef::Resource::User::LinuxUser.new("adam", @run_context) end - it "sets supports manage_home to true" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect( @new_resource.supports[:manage_home] ).to be true + it "supports manage_home does not exist", chef: ">= 13" do + expect( @new_resource.supports.key?(:manage_home) ).to be false + end + + it "supports non_unique does not exist", chef: ">= 13" do + expect( @new_resource.supports.key?(:non_unique) ).to be false + end + + # supports is a method on the superclass so can't totally be removed, but we should aggressively NOP it to decisively break it + it "disables the supports API", chef: ">= 13" do + @new_resource.supports( { manage_home: true } ) + expect( @new_resource.supports.key?(:manage_home) ).to be false + end + + it "sets supports manage_home to false" do + expect( @new_resource.supports[:manage_home] ).to be false + end + + it "sets supports non-unique to false" do + expect( @new_resource.supports[:non_unique] ).to be false end - it "sets supports non-unique to true" do + it "throws a deprecation warning on setting supports[:manage_home]" do Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect( @new_resource.supports[:non_unique] ).to be true + expect(Chef).to receive(:log_deprecation).with("supports { manage_home: true } on the user resource is deprecated and will be removed in Chef 13, set manage_home: true instead") + @new_resource.supports( { :manage_home => true } ) end - it "defaults manage_home to true" do + it "defaults manage_home to false" do expect( @new_resource.manage_home ).to be false end + it "supports[:manage_home] (incorectly) acts like manage_home" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + @new_resource.supports({ manage_home: true }) + expect( provider.useradd_options ).to eql(["-m"]) + end + + it "supports[:manage_home] does not change behavior of manage_home: false", chef: ">= 13" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + @new_resource.supports({ manage_home: true }) + expect( provider.useradd_options ).to eql(["-M"]) + end + it "by default manage_home is false and we use -M" do expect( provider.useradd_options ).to eql(["-M"]) end diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb index 624bcfc67d..fb7c9211a1 100644 --- a/spec/unit/provider/user/pw_spec.rb +++ b/spec/unit/provider/user/pw_spec.rb @@ -32,6 +32,8 @@ describe Chef::Provider::User::Pw do @new_resource.shell "/usr/bin/zsh" @new_resource.password "abracadabra" + # XXX: rip out in Chef-13 + Chef::Config[:treat_deprecation_warnings_as_errors] = false @new_resource.supports :manage_home => true @current_resource = Chef::Resource::User::PwUser.new("adam") diff --git a/spec/unit/provider/user/solaris_spec.rb b/spec/unit/provider/user/solaris_spec.rb index 860c9e41dd..8a5e654a0d 100644 --- a/spec/unit/provider/user/solaris_spec.rb +++ b/spec/unit/provider/user/solaris_spec.rb @@ -29,26 +29,31 @@ describe Chef::Provider::User::Solaris do Struct.new(:stdout, :stderr, :exitstatus) end - subject(:provider) do - p = described_class.new(@new_resource, @run_context) - p.current_resource = @current_resource + let(:node) do + Chef::Node.new.tap do |node| + node.automatic["platform"] = "solaris2" + end + end + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, {}, events) } + let(:new_resource) do + Chef::Resource::User::SolarisUser.new("adam", @run_context) + end + let(:current_resource) do + Chef::Resource::User::SolarisUser.new("adam", @run_context) + end - # Prevent the useradd-based provider tests from trying to write /etc/shadow - allow(p).to receive(:write_shadow_file) - p + subject(:provider) do + described_class.new(new_resource, run_context).tap do |p| + p.current_resource = current_resource + # Prevent the useradd-based provider tests from trying to write /etc/shadow + allow(p).to receive(:write_shadow_file) + end end describe "when we want to set a password" do before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::User::SolarisUser.new("adam", @run_context) - @current_resource = Chef::Resource::User::SolarisUser.new("adam", @run_context) - - @new_resource.password "hocus-pocus" - + new_resource.password "hocus-pocus" end it "should use its own shadow file writer to set the password" do @@ -68,53 +73,60 @@ describe Chef::Provider::User::Solaris do # may not be able to write to /etc for tests... temp_file = Tempfile.new("shadow") allow(Tempfile).to receive(:new).with("shadow", "/etc").and_return(temp_file) - @new_resource.password "verysecurepassword" + new_resource.password "verysecurepassword" provider.manage_user expect(::File.open(password_file.path, "r").read).to match(/adam:verysecurepassword:/) password_file.unlink end end - describe "when managing user locked status" do - before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::User::SolarisUser.new("dave") - @current_resource = @new_resource.dup + describe "#create_user" do + context "with a system user" do + before { new_resource.system(true) } + it "should not pass -r" do + expect(provider).to receive(:shell_out!).with("useradd", "adam") + provider.create_user + end + end - @provider = Chef::Provider::User::Solaris.new(@new_resource, @run_context) - @provider.current_resource = @current_resource + context "with manage_home" do + before { new_resource.manage_home(true) } + it "should not pass -r" do + expect(provider).to receive(:shell_out!).with("useradd", "-m", "adam") + provider.create_user + end end + end + + describe "when managing user locked status" do describe "when determining if the user is locked" do # locked shadow lines [ - "dave:LK:::::::", - "dave:*LK*:::::::", - "dave:*LK*foobar:::::::", - "dave:*LK*bahamas10:::::::", - "dave:*LK*L....:::::::", + "adam:LK:::::::", + "adam:*LK*:::::::", + "adam:*LK*foobar:::::::", + "adam:*LK*bahamas10:::::::", + "adam:*LK*L....:::::::", ].each do |shadow| it "should return true if user is locked with #{shadow}" do shell_return = shellcmdresult.new(shadow + "\n", "", 0) - expect(provider).to receive(:shell_out!).with("getent", "shadow", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("getent", "shadow", "adam").and_return(shell_return) expect(provider.check_lock).to eql(true) end end # unlocked shadow lines [ - "dave:NP:::::::", - "dave:*NP*:::::::", - "dave:foobar:::::::", - "dave:bahamas10:::::::", - "dave:L...:::::::", + "adam:NP:::::::", + "adam:*NP*:::::::", + "adam:foobar:::::::", + "adam:bahamas10:::::::", + "adam:L...:::::::", ].each do |shadow| it "should return false if user is unlocked with #{shadow}" do shell_return = shellcmdresult.new(shadow + "\n", "", 0) - expect(provider).to receive(:shell_out!).with("getent", "shadow", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("getent", "shadow", "adam").and_return(shell_return) expect(provider.check_lock).to eql(false) end end @@ -123,7 +135,7 @@ describe Chef::Provider::User::Solaris do describe "when locking the user" do it "should run passwd -l with the new resources username" do shell_return = shellcmdresult.new("", "", 0) - expect(provider).to receive(:shell_out!).with("passwd", "-l", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("passwd", "-l", "adam").and_return(shell_return) provider.lock_user end end @@ -131,7 +143,7 @@ describe Chef::Provider::User::Solaris do describe "when unlocking the user" do it "should run passwd -u with the new resources username" do shell_return = shellcmdresult.new("", "", 0) - expect(provider).to receive(:shell_out!).with("passwd", "-u", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("passwd", "-u", "adam").and_return(shell_return) provider.unlock_user end end diff --git a/spec/unit/resource/apt_update_spec.rb b/spec/unit/resource/apt_update_spec.rb index dd72b18063..a7d2c64fee 100644 --- a/spec/unit/resource/apt_update_spec.rb +++ b/spec/unit/resource/apt_update_spec.rb @@ -24,27 +24,35 @@ describe Chef::Resource::AptUpdate do let(:run_context) { Chef::RunContext.new(node, {}, events) } let(:resource) { Chef::Resource::AptUpdate.new("update", run_context) } - it "should create a new Chef::Resource::AptUpdate" do - expect(resource).to be_a_kind_of(Chef::Resource) - expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate) - end + context "on linux", :linux_only do + it "should create a new Chef::Resource::AptUpdate" do + expect(resource).to be_a_kind_of(Chef::Resource) + expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate) + end - it "the default frequency should be 1 day" do - expect(resource.frequency).to eql(86_400) - end + it "the default frequency should be 1 day" do + expect(resource.frequency).to eql(86_400) + end - it "the frequency should accept integers" do - resource.frequency(400) - expect(resource.frequency).to eql(400) - end + it "the frequency should accept integers" do + resource.frequency(400) + expect(resource.frequency).to eql(400) + end + + it "should resolve to a Noop class when apt-get is not found" do + expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false) + expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop) + end - it "should resolve to a Noop class when apt-get is not found" do - expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false) - expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop) + it "should resolve to a AptUpdate class when apt-get is found" do + expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true) + expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate) + end end - it "should resolve to a AptUpdate class when apt-get is found" do - expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true) - expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate) + context "on windows", :windows_only do + it "should resolve to a NoOp provider" do + expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop) + end end end diff --git a/spec/unit/resource/cab_package_spec.rb b/spec/unit/resource/cab_package_spec.rb new file mode 100644 index 0000000000..aa4890f171 --- /dev/null +++ b/spec/unit/resource/cab_package_spec.rb @@ -0,0 +1,38 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "spec_helper" + +describe Chef::Resource::CabPackage do + + let(:resource) { Chef::Resource::CabPackage.new("test_pkg") } + + it "creates a new Chef::Resource::CabPackage" do + expect(resource).to be_a_kind_of(Chef::Resource) + expect(resource).to be_a_kind_of(Chef::Resource::Package) + expect(resource).to be_a_instance_of(Chef::Resource::CabPackage) + end + + it "sets resource name as :cab_package" do + expect(resource.resource_name).to eql(:cab_package) + end + + it "coerce its name to a package_name" do + expect(resource.package_name).to eql("test_pkg") + end +end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 472c511857..d378da3ed0 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -94,19 +94,11 @@ describe Chef::Resource::RegistryKey, "values" do expect(@resource.values).to eql([ { :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" } ]) end - it "should throw an exception if the name field is missing" do + it "should raise an exception if the name field is missing" do expect { @resource.values [ { :type => :string, :data => "carmen" } ] }.to raise_error(ArgumentError) end - it "should throw an exception if the type field is missing" do - expect { @resource.values [ { :name => "poosh", :data => "carmen" } ] }.to raise_error(ArgumentError) - end - - it "should throw an exception if the data field is missing" do - expect { @resource.values [ { :name => "poosh", :type => :string } ] }.to raise_error(ArgumentError) - end - - it "should throw an exception if extra fields are present" do + it "should raise an exception if extra fields are present" do expect { @resource.values [ { :name => "poosh", :type => :string, :data => "carmen", :screwdriver => "sonic" } ] }.to raise_error(ArgumentError) end @@ -117,6 +109,30 @@ describe Chef::Resource::RegistryKey, "values" do it "should not allow an integer" do expect { @resource.send(:values, 100) }.to raise_error(ArgumentError) end + + it "should raise an exception if type of name is not string" do + expect { @resource.values([ { :name => 123, :type => :string, :data => "carmen" } ]) }.to raise_error(ArgumentError) + end + + it "should not raise an exception if type of name is string" do + expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error + end + + context "type key not given" do + it "should not raise an exception" do + expect { @resource.values([ { :name => "123", :data => "carmen" } ]) }.to_not raise_error + end + end + + context "type key given" do + it "should raise an exception if type of type is not symbol" do + expect { @resource.values([ { :name => "123", :type => "string", :data => "carmen" } ]) }.to raise_error(ArgumentError) + end + + it "should not raise an exception if type of type is symbol" do + expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error + end + end end describe Chef::Resource::RegistryKey, "recursive" do diff --git a/spec/unit/server_api_spec.rb b/spec/unit/server_api_spec.rb new file mode 100644 index 0000000000..05d2a28ed4 --- /dev/null +++ b/spec/unit/server_api_spec.rb @@ -0,0 +1,50 @@ +require "spec_helper" + +SIGNING_KEY_DOT_PEM = "-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA49TA0y81ps0zxkOpmf5V4/c4IeR5yVyQFpX3JpxO4TquwnRh +8VSUhrw8kkTLmB3cS39Db+3HadvhoqCEbqPE6915kXSuk/cWIcNozujLK7tkuPEy +YVsyTioQAddSdfe+8EhQVf3oHxaKmUd6waXrWqYCnhxgOjxocenREYNhZ/OETIei +PbOku47vB4nJK/0GhKBytL2XnsRgfKgDxf42BqAi1jglIdeq8lAWZNF9TbNBU21A +O1iuT7Pm6LyQujhggPznR5FJhXKRUARXBJZawxpGV4dGtdcahwXNE4601aXPra+x +PcRd2puCNoEDBzgVuTSsLYeKBDMSfs173W1QYwIDAQABAoIBAGF05q7vqOGbMaSD +2Q7YbuE/JTHKTBZIlBI1QC2x+0P5GDxyEFttNMOVzcs7xmNhkpRw8eX1LrInrpMk +WsIBKAFFEfWYlf0RWtRChJjNl+szE9jQxB5FJnWtJH/FHa78tR6PsF24aQyzVcJP +g0FGujBihwgfV0JSCNOBkz8MliQihjQA2i8PGGmo4R4RVzGfxYKTIq9vvRq/+QEa +Q4lpVLoBqnENpnY/9PTl6JMMjW2b0spbLjOPVwDaIzXJ0dChjNXo15K5SHI5mALJ +I5gN7ODGb8PKUf4619ez194FXq+eob5YJdilTFKensIUvt3YhP1ilGMM+Chi5Vi/ +/RCTw3ECgYEA9jTw4wv9pCswZ9wbzTaBj9yZS3YXspGg26y6Ohq3ZmvHz4jlT6uR +xK+DDcUiK4072gci8S4Np0fIVS7q6ivqcOdzXPrTF5/j+MufS32UrBbUTPiM1yoO +ECcy+1szl/KoLEV09bghPbvC58PFSXV71evkaTETYnA/F6RK12lEepcCgYEA7OSy +bsMrGDVU/MKJtwqyGP9ubA53BorM4Pp9VVVSCrGGVhb9G/XNsjO5wJC8J30QAo4A +s59ZzCpyNRy046AB8jwRQuSwEQbejSdeNgQGXhZ7aIVUtuDeFFdaIz/zjVgxsfj4 +DPOuzieMmJ2MLR4F71ocboxNoDI7xruPSE8dDhUCgYA3vx732cQxgtHwAkeNPJUz +dLiE/JU7CnxIoSB9fYUfPLI+THnXgzp7NV5QJN2qzMzLfigsQcg3oyo6F2h7Yzwv +GkjlualIRRzCPaCw4Btkp7qkPvbs1QngIHALt8fD1N69P3DPHkTwjG4COjKWgnJq +qoHKS6Fe/ZlbigikI6KsuwKBgQCTlSLoyGRHr6oj0hqz01EDK9ciMJzMkZp0Kvn8 +OKxlBxYW+jlzut4MQBdgNYtS2qInxUoAnaz2+hauqhSzntK3k955GznpUatCqx0R +b857vWviwPX2/P6+E3GPdl8IVsKXCvGWOBZWTuNTjQtwbDzsUepWoMgXnlQJSn5I +YSlLxQKBgQD16Gw9kajpKlzsPa6XoQeGmZALT6aKWJQlrKtUQIrsIWM0Z6eFtX12 +2jjHZ0awuCQ4ldqwl8IfRogWMBkHOXjTPVK0YKWWlxMpD/5+bGPARa5fir8O1Zpo +Y6S6MeZ69Rp89ma4ttMZ+kwi1+XyHqC/dlcVRW42Zl5Dc7BALRlJjQ== +-----END RSA PRIVATE KEY-----" + +describe Chef::ServerAPI do + let(:url) { "http://chef.example.com:4000" } + let(:key_path) { "/tmp/foo" } + + describe "#initialize" do + it "uses the configured key file" do + allow(IO).to receive(:read).with(key_path).and_return(SIGNING_KEY_DOT_PEM) + Chef::Config[:client_key] = key_path + + api = described_class.new(url) + expect(api.options[:signing_key_filename]).to eql(key_path) + end + + it "allows a user to set a raw_key" do + api = described_class.new(url, raw_key: SIGNING_KEY_DOT_PEM) + expect(api.options[:signing_key_filename]).to be_nil + expect(api.options[:raw_key]).to eql(SIGNING_KEY_DOT_PEM) + end + end +end diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb index 45fe8df40d..3f1210dbf1 100644 --- a/spec/unit/util/dsc/local_configuration_manager_spec.rb +++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb @@ -59,10 +59,6 @@ EOH allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) end context "that returns successfully" do - before(:each) do - allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) - end - let(:lcm_standard_output) { normal_lcm_output } let(:lcm_standard_error) { nil } let(:lcm_cmdlet_success) { true } @@ -138,4 +134,14 @@ EOH expect(lcm.send(:dsc_module_import_failure?, dsc_resource_import_failure_output.gsub("CimException", "ArgumentException"))).to be(false) end end + + describe "#run_configuration_cmdlet" do + context "when invalid dsc script is given" do + it "raises exception" do + configuration_document = "invalid-config" + shellout_flags = { :cwd => nil, :environment => nil, :timeout => nil } + expect { lcm.send(:run_configuration_cmdlet, configuration_document, true, shellout_flags) }.to raise_error(Chef::Exceptions::PowershellCmdletException) + end + end + end end diff --git a/version_policy.rb b/version_policy.rb index aa6ec3e4f4..bfe08e91e4 100644 --- a/version_policy.rb +++ b/version_policy.rb @@ -20,6 +20,7 @@ OMNIBUS_OVERRIDES = { # Lower level library pins ## according to comment in omnibus-sw, latest versions don't work on solaris # https://github.com/chef/omnibus-software/blob/aefb7e79d29ca746c3f843673ef5e317fa3cba54/config/software/libtool.rb#L23 + :bundler => "1.12.5", # until we figure out how to work with 1.13.0 "libffi" => "3.2.1", "libiconv" => "1.14", "liblzma" => "5.2.2", @@ -56,7 +57,7 @@ OMNIBUS_OVERRIDES = { # OMNIBUS_RUBYGEMS_AT_LATEST_VERSION = { rubygems: "rubygems-update", - bundler: "bundler", + # bundler: "bundler", # until we get working with 1.13.0 } # @@ -79,6 +80,7 @@ ACCEPTABLE_OUTDATED_GEMS = [ "rubocop", # chefstyle pins this, will often be somewhat behind "slop", # expected to disappear with pry 0.11 "typhoeus", # Until the travis gem updates to 1.0. + "cucumber-core", # Until cucumber 2.0 ] # |