diff options
| author | Stig Sandbeck Mathisen <ssm@debian.org> | 2012-08-22 11:28:55 +0200 |
|---|---|---|
| committer | Stig Sandbeck Mathisen <ssm@debian.org> | 2012-08-22 11:28:55 +0200 |
| commit | 97c9052b5300f4839ad436f304acba05c61e6ff5 (patch) | |
| tree | 8345adae24d9eb5fa3dd8f18f1b6cebd71abf260 | |
| parent | 3db2ecbab0afc76cee247e6c6974df3a3f4cd7ab (diff) | |
| parent | f0c112b18097ff4abd098d9b5659cf94628a2c74 (diff) | |
| download | puppet-upstream/2.7.19.tar.gz | |
Imported Upstream version 2.7.19upstream/2.7.19
136 files changed, 2158 insertions, 1190 deletions
@@ -1,3 +1,85 @@ +2.7.19 +=== +85f5543 Ruby 1.9.3 has a different error when `require` fails. +b2d08a4 (#15291) Add Vendor tag to Puppet spec file +7611753 Add packaging support for fedora 17 +b540aa0 (#15471) Fix setting mode of last_run_summary +7c7cffe (#15471) Ensure non-root can read report summary +a257105 Use Win32 API atomic replace in `replace_file` +a619bfd Add additional commits to CHANGELOG missed in 2.7.19rc1 +1dd660a (Maint) Remove reference to Patchwork +a26d1ee Replace "the short version" with outline +b73d0dd (#15595) Improve message on SSL errors +9567ec8 (#15595) Clear up tests around ssl errors +ccca77f use error_message instead of error +3809b59 updates as requested +e7b3049 (#15595) Offer better errors for certificate validation errors +6a43e96 Update CONTRIBUTING.md +c44973c (Maint) Remove some more ambiguity +c236001 Use rspec 2.11 compatible block syntax +b504ab7 Fix buggy resource title tests +00b563d (Maint) Be more honest about submission methods +b90c92b (Maint) Clarify that Redmine tickets are mandatory +62c14bd (Maint) Clarify which branches changes should be based on +c0a0a45 tidy.rb: Added info about the default value of 'type' to the doc. +2d994c2 Switch Rakefile off deprecated rake/gempackagetask +7324f54 Update main readme to have links to contrib and dev docs +57a74f7 (13070) Mark files as loaded before we load +a23cf6e (Maint) Don't assume paths are absolute +dd96d84 Determine packaging version with git describe +04fbccd Try again to avoid circular dependency in file indirections +3e23686 Avoid circular requirement in FileMetadata indirection +125ecec (Maint) Spec test wasn't testing anything +4c18d08 (#14964) Unlink Tempfiles consistently across different ruby versions +690c39b (Maint) Require the right file for md5 +44ada58 Extract host validation in store report processor +91df2f3 Use cross-platform absolute paths in file_serving tests +c7e4ca7 (#15221) Create /etc/puppet/modules directory for puppet module tool +c05489b (Maint:) Fix bad doc strings for two settings ("wether") +33fce73 Try again to avoid circular dependency in file indirections +b227aa1 Remove useless tests for Envelope +86ccca4 Clear deprecation warnings between tests +d7078c3 Avoid circular requirement in FileMetadata indirection +03d546e (Maint) Document common Windows issues +761b48f (#11868) Use `Installer` automation interface to query package state +cc4d8d2 Don't allow resource titles which aren't strings +37742db Eliminate require calls at runtime. +be5fcf4 Fix broken TransBucket transformation tests. +8f99187 Fix broken ability to remove resources from the catalog. +9bd4fd3 Fix type check when transforming catalog. +825b80d Fix all trivial "should to must" errors in our tests. +7a7bea7 Enforce "must not should" on Puppet::Type instances in tests. +39f0bf4 (#14962) PMT doesn't support setting a relative modulepath +39f425f (#15078) Document USR2 log rotation signal +300fce9 (#14909) Update createpackage.sh to resolve permissions issues +0d5a46a (#14600) Fix cleanup of tempfiles in file_spec +2141905 (maint) Add --test to puppet run +ddf8358 Update logrotate config to not restart puppetmasterd +da771cb (maint) Add symlink stub to gentoo service provider spec +0e87fe1 Add comment to upstart provider explaining exclusion of 'wait-for-state' +0219818 (#14531) Change default ensure value from symlink to link +0cab9ee Upstart code cleanup, init provider improvement +91628be Add spec test for network-interface-security +b60ad19 Add basic service resource test to upstart acceptance +a6245f9 Handle network-interface-security in upstart +60e37b6 Add exclude list to upstart provider +2911fec (#15027, #15028, #15029) Fix upstart version parsing +8efc492 (#13489) Use let to memoize instance variables +dc5f57c (#13489) Synchronously start and stop services +3ada851 (#14964) Don't fail if we can't unlink the Tempfile on Windows +0b01bb3 (#14860) Fix puppet cert exit status on failures +d7e77eb (#14749) Clear reference to invalid task after saving +a2d9597 (#13008) Allow scheduled task arguments to be specified +c6af946 (#13009) Compare scheduled task commands using backslashes +b572810 (#14599) Handle ENOTDIR in file type +2fc7191 (#9160) Change logging facility to debug for not supported provider features +0859364 (#13880) Add openrc spec - service with extreme long name +af6f7ba (#13880) Add openrc service provider for Gentoo and Funtoo +5146397 (#13379) Add path of pluginsync'd lenses to Augeas load_path automatically +087d5ae (#7285) Add spec for Augeas initialisation and file loading +06eb9a9 Fixes for #10915 and #11200 - user provider for AIX +ed73845 (#10354) added delete command to fix missing userdel flag in useradd provider + 2.7.18 === d804782 Reject directory traversal in store report processor diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd8e89720..a9a78744a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,88 +1,89 @@ -Checklist (and a short version for the impatient) +Checklist/Outline (The short version) ================================================= - * Commits: - - - Make commits of logical units. - - - Check for unnecessary whitespace with "git diff --check" before - committing. - - - Commit using Unix line endings (check the settings around "crlf" in - git-config(1)). - - - Do not check in commented out code or unneeded files. - - - The first line of the commit message should be a short - description (50 characters is the soft limit, excluding ticket - number(s)), and should skip the full stop. - - - If there is an associated Redmine ticket then the first line - should include the ticket number in the form "(#XXXX) Rest of - message". - - - The body should provide a meaningful commit message, which: - - - uses the imperative, present tense: "change", not "changed" or - "changes". - - - includes motivation for the change, and contrasts its - implementation with the previous behavior. - - - Make sure that you have tests for the bug you are fixing, or - feature you are adding. - - - Make sure the test suite passes after your commit (rake spec unit). - - * Submission: - - * Pre-requisites: - - - Make sure you have a [Redmine account](http://projects.puppetlabs.com) - - - Sign the [Contributor License Agreement](https://projects.puppetlabs.com/contributor_licenses/sign) - - * Preferred method: - - - Fork the repository on GitHub. - - - Push your changes to a topic branch in your fork of the - repository. - - - Submit a pull request to the repository in the puppetlabs - organization. - - * Alternate methods: - - - Mail patches to puppet-dev mailing list using `rake mail_patches`, - or `git-format-patch(1)` & `git-send-email(1)`. - - - Attach patches to Redmine ticket. - + * Getting Started: + - Make sure you have a [Redmine account](http://projects.puppetlabs.com) + - Submit a ticket for your issue, assuming one does not already exist. + - Decide what to base your work off of + * `2.6.x`: security fixes only + * `2.7.x`: bug fixes only + * `3.x`: new features that are not breaking changes + * `master`: new features that are breaking changes + + * Making Changes: + - Make sure you have a [GitHub account](https://github.com/signup/free) + - Fork the repository on GitHub + - Make commits of logical units. + - Check for unnecessary whitespace with "git diff --check" before committing. + - Make sure your commit messages are in the proper format + - Make sure you have added the necessary tests for your changes + - Run _all_ the tests to assure nothing else was accidentally broken + + * Submitting Changes: + - Sign the [Contributor License Agreement](https://projects.puppetlabs.com/contributor_licenses/sign) + - Push your changes to a topic branch in your fork of the repository. + - Submit a pull request to the repository in the puppetlabs organization. + - Update your Redmine ticket + The long version ================ - 0. Decide what to base your work on. - - In general, you should always base your work on the oldest - branch that your change is relevant to. - - - A bug fix should be based on the current stable series. If the - bug is not present in the current stable release, then base it on - `master`. - - - A new feature should be based on `master`. - - - Security fixes should be based on the current maintenance series - (that is, the previous stable series). If the security issue - was not present in the maintenance series, then it should be - based on the current stable series if it was introduced there, - or on `master` if it is not yet present in a stable release. - - The current stable series is 2.7.x, and the current maintenance - series is 2.6.x. - - 1. Make separate commits for logically separate changes. + 0. Create a Redmine ticket for the change you'd like to make. + + It's very important that there be a Redmine ticket for the change + you are making. Considering the number of contributions which are + submitted, it is crucial that we know we can find the ticket on Redmine. + + Before making a ticket however, be sure that one does not already exist. + You can do this by searching Redmine or by trying a Google search which + includes `sites:projects.puppetlabs.com` in addition to some of the keywords + related to your issue. + + If you do not find a ticket that that accurately describes the work + you're going to be doing, go ahead and create one. But be sure to + look for related tickets and add them to the 'related tickets' section. + + 1. Decide what to base your work on. + + In general, you should always base your work on the oldest + branch that your change is relevant to, and it will be + eventually merged up. Currently, branches will be merged up as + follows: + 2.6.x => 2.7.x => 3.x => master + + Currently, this is how you should decide where to target your changes: + + The absolute earliest place something should be targeted is at `2.6.x`, + and these should _only_ be security fixes. Anything else must be + targeted at a later branch. + + A bug fix should be based off the the earliest place where it is + relevant. If it first appears in `2.7.x`, then it should be + targeted here and eventually merged up to `3.x` and master. + + New features which are _backwards compatible_ should be targeted + at the next release, which currently is `3.x`. + + New features that are _breaking changes_ should be targeted at + `master`. + + Part of deciding what to what your work should be based off of includes naming + your topic branch to reflect this. Your branch name should have the following + format: + `ticket/target_branch/ticket_number_short_description_of_issuee` + + For example, if you are fixing a bug relating to the ssl spec, which has Redmine + ticket number 12345, then your branch should be named: + `ticket/2.7.x/12345_fix_ssl_spec_tests` + + There is a good chance that if you submit a pull request _from_ master _to_ master, + Puppet Labs developers will suspect that you're not sure about the process. This is + why clear naming of branches and basing your work off the right place will be + extremely helpful in ensuring that your submission is reviewed and merged. Often times + if your change is targeted at the wrong place, we will bounce it back to you and wait + to review it until it has been retargeted. + + 2. Make separate commits for logically separate changes. Please break your commits down into logically consistent units which include new or changed tests relevent to the rest of the @@ -94,7 +95,7 @@ The long version If you're going to refactor a piece of code, please do so as a separate commit from your feature or bug fix changes. - We also really appreciate changes that include tests to make + It's crucial that your changes include tests to make sure the bug isn't re-introduced, and that the feature isn't accidentally broken. @@ -115,7 +116,11 @@ The long version whitespaces or other "whitespace errors". You can do this by running "git diff --check" on your changes before you commit. - 2. Sign the Contributor License Agreement + When writing commit messages, please be sure they meet + [these standards](https://github.com/erlang/otp/wiki/Writing-good-commit-messages), and please include the ticket number in your + short summary. It should look something like this: `(#12345) Fix this issue in Puppet` + + 3. Sign the Contributor License Agreement Before we can accept your changes, we do need a signed Puppet Labs Contributor License Agreement (CLA). @@ -131,106 +136,46 @@ The long version If you have any questions about the CLA, please feel free to contact Puppet Labs via email at cla-submissions@puppetlabs.com. - 3. Sending your patches - - We accept multiple ways of submitting your changes for - inclusion. They are listed below in order of preference. - - Please keep in mind that any method that involves sending email - to the mailing list directly requires you to be subscribed to - the mailing list, and that your first post to the list will be - held in a moderation queue. - - * GitHub Pull Requests - - To submit your changes via a GitHub pull request, we _highly_ - recommend that you have them on a topic branch, instead of - directly on "master" or one of the release, or RC branches. - It makes things much easier to keep track of, especially if - you decide to work on another thing before your first change - is merged in. + 4. Sending your patches - GitHub has some pretty good - [general documentation](http://help.github.com/) on using - their site. They also have documentation on - [creating pull requests](http://help.github.com/send-pull-requests/). + To submit your changes via a GitHub pull request, you must + have them on a topic branch, instead of directly on "master" + or one of the release, or RC branches. It makes things much easier + to keep track of, especially if you decide to work on another thing + before your first change is merged in. - In general, after pushing your topic branch up to your - repository on GitHub, you'll switch to the branch in the - GitHub UI and click "Pull Request" towards the top of the page - in order to open a pull request. + GitHub has some pretty good + [general documentation](http://help.github.com/) on using + their site. They also have documentation on + [creating pull requests](http://help.github.com/send-pull-requests/). - You'll want to make sure that you have the appropriate - destination branch in the repository under the puppetlabs - organization. This should be the same branch that you based - your changes off of. + In general, after pushing your topic branch up to your + repository on GitHub, you'll switch to the branch in the + GitHub UI and click "Pull Request" towards the top of the page + in order to open a pull request. - * Other pull requests + You'll want to make sure that you have the appropriate + destination branch in the repository under the puppetlabs + organization. This should be the same branch that you based + your changes off of. - If you already have a publicly accessible version of the - repository hosted elsewhere, and don't wish to or cannot use - GitHub, you can submit your change by requesting that we pull - the changes from your repository by sending an email to the - puppet-dev Google Groups mailing list. + 5. Update the related Redmine ticket. - `git-request-pull(1)` provides a handy way to generate the text - for the email requesting that we pull your changes (and does - some helpful sanity checks in the process). - - * Mailing patches to the mailing list - - If neither of the previous methods works for you, then you can - also mail the patches inline to the puppet-dev Google Group - using either `rake mail_patches`, or by using - `git-format-patch(1)`, and `git-send-email(1)` directly. - - `rake mail_patches` handles setting the appropriate flags to - `git-format-patch(1)` and `git-send-email(1)` for you, but - doesn't allow adding any commentary between the '---', and the - diffstat in the resulting email. It also requires that you - have created your topic branch in the form - `<type>/<parent>/<name>`. - - If you decide to use `git-format-patch(1)` and - `git-send-email(1)` directly, please be sure to use the - following flags for `git-format-patch(1)`: -C -M -s -n - --subject-prefix='PATCH/puppet' - - * Attaching patches to Redmine - - As a method of last resort you can also directly attach the - output of `git-format-patch(1)`, or `git-diff(1)` to a Redmine - ticket. - - If you are generating the diff outside of Git, please be sure - to generate a unified diff. - - 4. Update the related Redmine ticket. - - If there's a Redmine ticket associated with the change you - submitted, then you should update the ticket to include the - location of your branch, and change the status to "In Topic - Branch Pending Merge", along with any other commentary you may - wish to make. + You should update the Redmine ticket associated + with the change you submitted to include the location of your branch + on the `branch` field of the ticket, and change the status to + "In Topic Branch Pending Review", along with any other commentary + you may wish to make. How to track the status of your change after it's been submitted ================================================================ -Shortly after opening a pull request on GitHub, there should be an -automatic message sent to the puppet-dev Google Groups mailing list -notifying people of this. This notification is used to let the Puppet +Shortly after opening a pull request, there should be an automatic +email sent via GitHub. This notification is used to let the Puppet development community know about your requested change to give them a chance to review, test, and comment on the change(s). -If you submitted your change via manually sending a pull request or -mailing the patches, then we keep track of these using -[patchwork](https://patchwork.puppetlabs.com). When code is merged -into the project it is automatically removed from patchwork, and the -Redmine ticket is manually updated with the commit SHA1. In addition, -the ticket status must be updated by the person who merges the topic -branch to a status of "Merged - Pending Release" - -We do our best to comment on or merge submitted changes within a week. +We do our best to comment on or merge submitted changes within a about week. However, if there hasn't been any commentary on the pull request or mailed patches, and it hasn't been merged in after a week, then feel free to ask for an update by replying on the mailing list to the @@ -246,8 +191,6 @@ Additional Resources * [Bug tracker (Redmine)](http://projects.puppetlabs.com) -* [Patchwork](https://patchwork.puppetlabs.com) - * [Contributor License Agreement](https://projects.puppetlabs.com/contributor_licenses/sign) * [General GitHub documentation](http://help.github.com/) @@ -8,6 +8,7 @@ configurations) based on a centralized specification. Documentation (and detailed installation instructions) can be found online at the [Puppet Docs site](http://docs.puppetlabs.com). + Installation ------------ @@ -32,6 +33,13 @@ Generally, you need the following things installed: * Facter => 1.5.1 (available via your package manager or from the [Facter site](http://puppetlabs.com/projects/facter). +Contributions +------ +Please see our [Contibution +Documents](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md) +and our [Developer +Documentation](https://github.com/puppetlabs/puppet/blob/master/README_DEVELOPER.md). + License ------- diff --git a/README_DEVELOPER.md b/README_DEVELOPER.md index aa6fb2bf4..75e123509 100644 --- a/README_DEVELOPER.md +++ b/README_DEVELOPER.md @@ -63,9 +63,7 @@ SyntaxError, invalid multibyte escape as mentioned above. # Windows # If you'd like to run Puppet from source on Windows platforms, the -include `ext/envpuppet.bat` will help. All file paths in the Puppet -code base should use a path separator of / regardless of Windows or -Unix filesystem. +include `ext/envpuppet.bat` will help. To quickly run Puppet from source, assuming you already have Ruby installed from [rubyinstaller.org](http://rubyinstaller.org). @@ -88,4 +86,41 @@ on Windows, so use the following rspec exclude filter: This will give you a shared filesystem with your Mac and allow you to run Puppet directly from source without using install.rb or copying files around. +## Common Issues ## + + * Don't assume file paths start with '/', as that is not a valid path on + Windows. Use Puppet::Util.absolute_path? to validate that a path is fully + qualified. + + * Use File.expand_path('/tmp') in tests to generate a fully qualified path + that is valid on POSIX and Windows. In the latter case, the current working + directory will be used to expand the path. + + * Always use binary mode when performing file I/O, unless you explicitly want + Ruby to translate between unix and dos line endings. For example, opening an + executable file in text mode will almost certainly corrupt the resulting + stream, as will occur when using: + + IO.open(path, 'r') { |f| ... } + IO.read(path) + + If in doubt, specify binary mode explicitly: + + IO.open(path, 'rb') + + * Don't assume file paths are separated by ':'. Use File::PATH_SEPARATOR + instead, which is ':' on POSIX and ';' on Windows. + + * On Windows, File::SEPARATOR is '/', and File::ALT_SEPARATOR is '\'. On + POSIX systems, File::ALT_SEPARATOR is nil. In general, use '/' as the + separator as most Windows APIs, e.g. CreateFile, accept both types of + separators. + + * Don't use waitpid/waitpid2 if you need the child process' exit code, + as the child process may exit before it has a chance to open the + child's HANDLE and retrieve its exit code. Use Puppet::Util.execute. + + * Don't assume 'C' drive. Use environment variables to look these up: + + "#{ENV['windir']}/system32/netsh.exe" EOF @@ -2,14 +2,30 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), 'tasks') +begin + require 'rubygems' + require 'rubygems/package_task' +rescue LoadError + # Users of older versions of Rake (0.8.7 for example) will not necessarily + # have rubygems installed, or the newer rubygems package_task for that + # matter. + require 'rake/packagetask' + require 'rake/gempackagetask' +end + require 'rake' -require 'rake/packagetask' -require 'rake/gempackagetask' require 'rspec' require "rspec/core/rake_task" + module Puppet - PUPPETVERSION = File.read('lib/puppet.rb')[/PUPPETVERSION *= *'(.*)'/,1] or fail "Couldn't find PUPPETVERSION" + %x{which git &> /dev/null} + if $?.success? and File.exist?('.git') + # remove the git hash from git describe string + PUPPETVERSION=%x{git describe}.chomp.gsub('-','.').split('.')[0..3].join('.') + else + PUPPETVERSION=File.read('lib/puppet.rb')[/PUPPETVERSION *= *'(.*)'/,1] or fail "Couldn't find PUPPETVERSION" + end end Dir['tasks/**/*.rake'].each { |t| load t } diff --git a/conf/osx/createpackage.sh b/conf/osx/createpackage.sh index 0c153f25a..0f63ec8fa 100755 --- a/conf/osx/createpackage.sh +++ b/conf/osx/createpackage.sh @@ -53,6 +53,7 @@ function install_puppet() { "${installer}" --destdir="${pkgroot}" --bindir="${BINDIR}" --sbindir="${SBINDIR}" --sitelibdir="${SITELIBDIR}" mkdir -p ${pkgroot}/var/lib/puppet chown -R root:admin "${pkgroot}" + chmod -R go-w "${pkgroot}" } function install_docs() { @@ -107,7 +108,8 @@ function create_package() { rm -fr "$(pwd)/puppet-${puppet_version}.pkg" echo "Building package" echo "Note that packagemaker is reknowned for spurious errors. Don't panic." - "${PACKAGEMAKER}" --root "${pkgroot}" \ + "${PACKAGEMAKER}" --verbose --no-recommend --no-relocate \ + --root "${pkgroot}" \ --info "${pkgtemp}/${PROTO_PLIST}" \ --scripts ${pkgtemp}/scripts \ --out "$(pwd)/puppet-${puppet_version}.pkg" diff --git a/conf/redhat/logrotate b/conf/redhat/logrotate index c3a4d437a..385e6e8da 100644 --- a/conf/redhat/logrotate +++ b/conf/redhat/logrotate @@ -4,7 +4,7 @@ create 0644 puppet puppet sharedscripts postrotate - [ -e /etc/init.d/puppetmaster ] && /etc/init.d/puppetmaster condrestart >/dev/null 2>&1 || true + pkill -USR2 -u puppet -f /usr/sbin/puppetmasterd || true [ -e /etc/init.d/puppet ] && /etc/init.d/puppet reload > /dev/null 2>&1 || true endscript } diff --git a/conf/redhat/puppet.spec b/conf/redhat/puppet.spec index 89e7f5129..3e78958ea 100644 --- a/conf/redhat/puppet.spec +++ b/conf/redhat/puppet.spec @@ -1,20 +1,28 @@ # Augeas and SELinux requirements may be disabled at build time by passing # --without augeas and/or --without selinux to rpmbuild or mock -%{!?ruby_sitelibdir: %global ruby_sitelibdir %(ruby -rrbconfig -e 'puts Config::CONFIG["sitelibdir"]')} +# Fedora 17 ships with Ruby 1.9, which uses vendorlibdir instead of +# sitelibdir. Adjust our target if installing on f17. +%if 0%{?fedora} >= 17 +%global puppet_libdir %(ruby -rrbconfig -e 'puts RbConfig::CONFIG["vendorlibdir"]') +%else +%global puppet_libdir %(ruby -rrbconfig -e 'puts RbConfig::CONFIG["sitelibdir"]') +%endif + %global confdir conf/redhat Name: puppet -Version: 2.7.18 -#Release: 0.1rc1.2%{?dist} +Version: 2.7.19 +#Release: 0.1rc3%{?dist} Release: 1%{?dist} +Vendor: %{?_host_vendor} Summary: A network tool for managing many disparate systems License: ASL 2.0 URL: http://puppetlabs.com Source0: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}.tar.gz -#Source0: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc1.tar.gz +#Source0: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc3.tar.gz Source1: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}.tar.gz.asc -#Source1: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc1.tar.gz.asc +#Source1: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc3.tar.gz.asc Group: System Environment/Base @@ -67,7 +75,7 @@ The server can also function as a certificate authority and file server. %prep %setup -q -n %{name}-%{version} -#%setup -q -n %{name}-%{version}rc1 +#%setup -q -n %{name}-%{version}rc3 patch -s -p1 < conf/redhat/rundir-perms.patch @@ -91,7 +99,7 @@ mv conf/puppet-queue.conf examples/etc/puppet/ %install rm -rf %{buildroot} -ruby install.rb --destdir=%{buildroot} --quick --no-rdoc +ruby install.rb --destdir=%{buildroot} --quick --no-rdoc --sitelibdir=%{puppet_libdir} install -d -m0755 %{buildroot}%{_sysconfdir}/puppet/manifests install -d -m0755 %{buildroot}%{_datadir}/%{name}/modules @@ -136,6 +144,9 @@ echo "D /var/run/%{name} 0755 %{name} %{name} -" > \ %{buildroot}%{_sysconfdir}/tmpfiles.d/%{name}.conf %endif +# Create puppet modules directory for puppet module tool +mkdir -p %{buildroot}%{_sysconfdir}/%{name}/modules + %files %defattr(-, root, root, 0755) %doc CHANGELOG LICENSE README.md examples @@ -146,9 +157,10 @@ echo "D /var/run/%{name} 0755 %{name} %{name} -" > \ %{_bindir}/puppetdoc %{_sbindir}/puppetca %{_sbindir}/puppetd -%{ruby_sitelibdir}/* +%{puppet_libdir}/* %{_initrddir}/puppet %dir %{_sysconfdir}/puppet +%dir %{_sysconfdir}/%{name}/modules %if 0%{?fedora} >= 15 %config(noreplace) %{_sysconfdir}/tmpfiles.d/%{name}.conf %endif @@ -289,6 +301,21 @@ fi rm -rf %{buildroot} %changelog +* Tue Aug 21 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.19-1 +- Update for 2.7.19 + +* Tue Aug 14 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.19-0.1rc3 +- Update for 2.7.19rc3 + +* Tue Aug 7 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.19-0.1rc2 +- Update for 2.7.19rc2 + +* Wed Aug 1 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.19-0.1rc1 +- Update for 2.7.19rc1 + +* Wed Jul 11 2012 William Hopper <whopper@puppetlabs.com> - 2.7.18-2 +- (#15221) Create /etc/puppet/modules for puppet module tool + * Mon Jul 9 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.18-1 - Update for 2.7.18 diff --git a/lib/puppet.rb b/lib/puppet.rb index a4134ecae..f45f7c77e 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -24,7 +24,7 @@ require 'puppet/util/run_mode' # it's also a place to find top-level commands like 'debug' module Puppet - PUPPETVERSION = '2.7.18' + PUPPETVERSION = '2.7.19' def Puppet.version PUPPETVERSION diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb index eab02d0f6..0c6485b08 100644 --- a/lib/puppet/application/agent.rb +++ b/lib/puppet/application/agent.rb @@ -293,6 +293,8 @@ Puppet agent accepts the following signals: Shut down the puppet agent daemon. * SIGUSR1: Immediately retrieve and apply configurations from the puppet master. +* SIGUSR2: + Close file descriptors for log files and reopen them. Used with logrotate. AUTHOR ------ diff --git a/lib/puppet/application/master.rb b/lib/puppet/application/master.rb index f4f4cbdea..97c243c71 100644 --- a/lib/puppet/application/master.rb +++ b/lib/puppet/application/master.rb @@ -112,6 +112,8 @@ following signals: Restart the puppet master server. * SIGINT and SIGTERM: Shut down the puppet master server. +* SIGUSR2: + Close file descriptors for log files and reopen them. Used with logrotate. AUTHOR ------ diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb index 208a6f85a..6d0a09064 100644 --- a/lib/puppet/configurer.rb +++ b/lib/puppet/configurer.rb @@ -180,9 +180,8 @@ class Puppet::Configurer def save_last_run_summary(report) mode = Puppet.settings.setting(:lastrunfile).mode - Puppet::Util::FileLocking.writelock(Puppet[:lastrunfile]) do |file| - file.chmod(mode) - file.print YAML.dump(report.raw_summary) + Puppet::Util.replace_file(Puppet[:lastrunfile], mode) do |fh| + fh.print YAML.dump(report.raw_summary) end rescue => detail puts detail.backtrace if Puppet[:trace] diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 56223bb53..f44a348e2 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -180,9 +180,10 @@ module Puppet end }, :thin_storeconfigs => {:default => false, :desc => - "Boolean; wether storeconfigs store in the database only the facts and exported resources. - If true, then storeconfigs performance will be higher and still allow exported/collected - resources, but other usage external to Puppet might not work", + "Boolean; whether Puppet should store only facts and exported resources in the storeconfigs + database. This will improve the performance of exported resources with the older + `active_record` backend, but will disable external tools that search the storeconfigs database. + Thinning catalogs is generally unnecessary when using PuppetDB to store catalogs.", :hook => proc do |value| Puppet.settings[:storeconfigs] = true if value end @@ -505,7 +506,7 @@ EOT rest indirections. This can be used as a fine-grained authorization system for `puppet master`." ], - :ca => [true, "Wether the master should function as a certificate authority."], + :ca => [true, "Whether the master should function as a certificate authority."], :modulepath => { :default => "$confdir/modules#{File::PATH_SEPARATOR}/usr/share/puppet/modules", :desc => "The search path for modules, as a list of directories separated by the system path separator character. (The POSIX path separator is ':', and the Windows path separator is ';'.)", @@ -713,7 +714,7 @@ EOT "Whether to send reports after every transaction." ], :lastrunfile => { :default => "$statedir/last_run_summary.yaml", - :mode => 0640, + :mode => 0644, :desc => "Where puppet agent stores the last run report summary in yaml format." }, :lastrunreport => { :default => "$statedir/last_run_report.yaml", diff --git a/lib/puppet/face/module/install.rb b/lib/puppet/face/module/install.rb index 68eebec87..d7dc84536 100644 --- a/lib/puppet/face/module/install.rb +++ b/lib/puppet/face/module/install.rb @@ -147,13 +147,14 @@ Puppet::Face.define(:module, '1.0.0') do when_invoked do |name, options| sep = File::PATH_SEPARATOR + if options[:target_dir] - options[:target_dir] = File.expand_path(options[:target_dir]) options[:modulepath] = "#{options[:target_dir]}#{sep}#{options[:modulepath]}" end Puppet.settings[:modulepath] = options[:modulepath] options[:target_dir] = Puppet.settings[:modulepath].split(sep).first + options[:target_dir] = File.expand_path(options[:target_dir]) Puppet.notice "Preparing to install into #{options[:target_dir]} ..." Puppet::ModuleTool::Applications::Installer.run(name, options) diff --git a/lib/puppet/file_bucket/dipper.rb b/lib/puppet/file_bucket/dipper.rb index 4adab5df0..8e35bde67 100644 --- a/lib/puppet/file_bucket/dipper.rb +++ b/lib/puppet/file_bucket/dipper.rb @@ -1,3 +1,4 @@ +require 'pathname' require 'puppet/file_bucket' require 'puppet/file_bucket/file' require 'puppet/indirector/request' @@ -99,7 +100,6 @@ class Puppet::FileBucket::Dipper private def absolutize_path( path ) - require 'pathname' Pathname.new(path).realpath end diff --git a/lib/puppet/indirector/file_content.rb b/lib/puppet/indirector/file_content.rb index 5261ddc05..5528b6263 100644 --- a/lib/puppet/indirector/file_content.rb +++ b/lib/puppet/indirector/file_content.rb @@ -1,5 +1,5 @@ -require 'puppet/file_serving/content' - # A stub class, so our constants work. class Puppet::Indirector::FileContent # :nodoc: end + +require 'puppet/file_serving/content' diff --git a/lib/puppet/indirector/file_metadata.rb b/lib/puppet/indirector/file_metadata.rb index c43579d24..2a90955f6 100644 --- a/lib/puppet/indirector/file_metadata.rb +++ b/lib/puppet/indirector/file_metadata.rb @@ -1,5 +1,5 @@ -require 'puppet/file_serving/metadata' - # A stub class, so our constants work. class Puppet::Indirector::FileMetadata # :nodoc: end + +require 'puppet/file_serving/metadata' diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb index 7296be2b9..e2b183639 100644 --- a/lib/puppet/indirector/indirection.rb +++ b/lib/puppet/indirector/indirection.rb @@ -10,6 +10,9 @@ class Puppet::Indirector::Indirection include Puppet::Util::Docs extend Puppet::Util::Instrumentation::Instrumentable + attr_accessor :name, :model + attr_reader :termini + probe :find, :label => Proc.new { |parent, key, *args| "find_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }} probe :save, :label => Proc.new { |parent, key, *args| "save_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }} probe :search, :label => Proc.new { |parent, key, *args| "search_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }} @@ -36,10 +39,6 @@ class Puppet::Indirector::Indirection match.model end - attr_accessor :name, :model - - attr_reader :termini - # Create and return our cache terminus. def cache raise(Puppet::DevError, "Tried to cache when no cache class was set") unless cache_class diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index d76a2890f..717937453 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -80,21 +80,27 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus def http_request(method, request, *args) http_connection = network(request) peer_certs = [] + verify_errors = [] - # We add the callback to collect the certificates for use in constructing - # the error message if the verification failed. This is necessary since we - # don't have direct access to the cert that we expected the connection to - # use otherwise. - # http_connection.verify_callback = proc do |preverify_ok, ssl_context| + # We use the callback to collect the certificates for use in constructing + # the error message if the verification failed. This is necessary since we + # don't have direct access to the cert that we expected the connection to + # use otherwise. peer_certs << Puppet::SSL::Certificate.from_s(ssl_context.current_cert.to_pem) + # And also keep the detailed verification error if such an error occurs + if ssl_context.error_string and not preverify_ok + verify_errors << "#{ssl_context.error_string} for #{ssl_context.current_cert.subject}" + end preverify_ok end http_connection.send(method, *args) rescue OpenSSL::SSL::SSLError => error if error.message.include? "certificate verify failed" - raise Puppet::Error, "#{error.message}. This is often because the time is out of sync on the server or client" + msg = error.message + msg << ": [" + verify_errors.join('; ') + "]" + raise Puppet::Error, msg elsif error.message =~ /hostname (was )?not match/ raise unless cert = peer_certs.find { |c| c.name !~ /^puppet ca/i } diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index 5c9af4f96..1226507f5 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -1,11 +1,10 @@ require 'puppet/interface/action' +require 'puppet/interface/action_builder' module Puppet::Interface::ActionManager # Declare that this app can take a specific action, and provide # the code to do so. def action(name, &block) - require 'puppet/interface/action_builder' - @actions ||= {} raise "Action #{name} already defined for #{self}" if action?(name) diff --git a/lib/puppet/module_tool/applications/unpacker.rb b/lib/puppet/module_tool/applications/unpacker.rb index e9b0b50d1..3ed6058f3 100644 --- a/lib/puppet/module_tool/applications/unpacker.rb +++ b/lib/puppet/module_tool/applications/unpacker.rb @@ -21,16 +21,35 @@ module Puppet::ModuleTool @module_dir end + # Obtain a suitable temporary path for building and unpacking tarballs + # + # @return [Pathname] path to temporary build location + def build_dir + Puppet::Forge::Cache.base_path + "tmp-unpacker-#{Digest::SHA1.hexdigest(@filename.basename.to_s)}" + end + private def extract_module_to_install_dir delete_existing_installation_or_abort! - build_dir = Puppet::Forge::Cache.base_path + "tmp-unpacker-#{Digest::SHA1.hexdigest(@filename.basename.to_s)}" build_dir.mkpath begin - unless system "tar xzf #{@filename} -C #{build_dir}" - raise RuntimeError, "Could not extract contents of module archive." + begin + if Facter.value('operatingsystem') == "Solaris" + # Solaris tar is not as safe and works differently, so we prefer + # gnutar instead. + if Puppet::Util.which('gtar') + Puppet::Util.execute("gtar xzf #{@filename} -C #{build_dir}") + else + raise RuntimeError, "Cannot find the command 'gtar'. Make sure GNU tar is installed, and is in your PATH." + end + else + Puppet::Util.execute("tar xzf #{@filename} -C #{build_dir}") + end + rescue Puppet::ExecutionFailure => e + raise RuntimeError, "Could not extract contents of module archive: #{e.message}" end + # grab the first directory extracted = build_dir.children.detect { |c| c.directory? } FileUtils.mv extracted, @module_dir diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb index 5548f40fb..c0d5756f1 100755 --- a/lib/puppet/network/handler/fileserver.rb +++ b/lib/puppet/network/handler/fileserver.rb @@ -645,9 +645,9 @@ class Puppet::Network::Handler nil end + require 'puppet/file_serving' + require 'puppet/file_serving/fileset' def reclist(abspath, recurse, ignore) - require 'puppet/file_serving' - require 'puppet/file_serving/fileset' if recurse.is_a?(Fixnum) args = { :recurse => true, :recurselimit => recurse, :links => :follow } else diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb index ce3c499c5..b0b4d2652 100644 --- a/lib/puppet/parser/ast/resource.rb +++ b/lib/puppet/parser/ast/resource.rb @@ -32,14 +32,21 @@ class Resource < AST::Branch resource_titles = instance.title.safeevaluate(scope) # it's easier to always use an array, even for only one name - resource_titles = [resource_titles] unless resource_titles.is_a?(Array) + resource_titles = [resource_titles].flatten.collect do |title| + case title + when ::String, ::Numeric, ::Symbol, true, false + title.to_s + else + raise Puppet::ParseError, "Resource title must be a String, not #{title.class}" + end + end fully_qualified_type, resource_titles = scope.resolve_type_and_titles(type, resource_titles) # Second level of implicit iteration; build a resource for each # title. This handles things like: # file { ['/foo', '/bar']: owner => blah } - resource_titles.flatten.collect { |resource_title| + resource_titles.collect { |resource_title| exceptwrap :type => Puppet::ParseError do resource = Puppet::Parser::Resource.new( fully_qualified_type, resource_title, diff --git a/lib/puppet/parser/functions/fqdn_rand.rb b/lib/puppet/parser/functions/fqdn_rand.rb index 93ab98bcd..dd8d56800 100644 --- a/lib/puppet/parser/functions/fqdn_rand.rb +++ b/lib/puppet/parser/functions/fqdn_rand.rb @@ -1,3 +1,5 @@ +require 'digest/md5' + Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc => "Generates random numbers based on the node's fqdn. Generated random values will be a range from 0 up to and excluding n, where n is the first parameter. @@ -5,7 +7,6 @@ Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc => $random_number = fqdn_rand(30) $random_number_seed = fqdn_rand(30,30)") do |args| - require 'digest/md5' max = args.shift srand(Digest::MD5.hexdigest([lookupvar('::fqdn'),args].join(':')).hex) rand(max).to_s diff --git a/lib/puppet/parser/functions/md5.rb b/lib/puppet/parser/functions/md5.rb index f7a4f7222..d1e1efae2 100644 --- a/lib/puppet/parser/functions/md5.rb +++ b/lib/puppet/parser/functions/md5.rb @@ -1,5 +1,5 @@ -Puppet::Parser::Functions::newfunction(:md5, :type => :rvalue, :doc => "Returns a MD5 hash value from a provided string.") do |args| - require 'md5' +require 'digest/md5' +Puppet::Parser::Functions::newfunction(:md5, :type => :rvalue, :doc => "Returns a MD5 hash value from a provided string.") do |args| Digest::MD5.hexdigest(args[0]) end diff --git a/lib/puppet/parser/functions/sha1.rb b/lib/puppet/parser/functions/sha1.rb index 1e7d5abe4..c52df4d28 100644 --- a/lib/puppet/parser/functions/sha1.rb +++ b/lib/puppet/parser/functions/sha1.rb @@ -1,5 +1,5 @@ -Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue, :doc => "Returns a SHA1 hash value from a provided string.") do |args| - require 'digest/sha1' +require 'digest/sha1' +Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue, :doc => "Returns a SHA1 hash value from a provided string.") do |args| Digest::SHA1.hexdigest(args[0]) end diff --git a/lib/puppet/parser/functions/template.rb b/lib/puppet/parser/functions/template.rb index 8105e2cac..5e4b00e1e 100644 --- a/lib/puppet/parser/functions/template.rb +++ b/lib/puppet/parser/functions/template.rb @@ -5,8 +5,6 @@ Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :doc => Note that if multiple templates are specified, their output is all concatenated and returned as the output of the function.") do |vals| - require 'erb' - vals.collect do |file| # Use a wrapper, so the template can't get access to the full # Scope object. diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb index 65579a820..861a098a5 100644 --- a/lib/puppet/parser/type_loader.rb +++ b/lib/puppet/parser/type_loader.rb @@ -1,3 +1,4 @@ +require 'find' require 'puppet/node/environment' class Puppet::Parser::TypeLoader @@ -93,8 +94,6 @@ class Puppet::Parser::TypeLoader end def import_all - require 'find' - module_names = [] # Collect the list of all known modules environment.modulepath.each do |path| diff --git a/lib/puppet/provider/augeas/augeas.rb b/lib/puppet/provider/augeas/augeas.rb index 6998121d7..75ea9b940 100644 --- a/lib/puppet/provider/augeas/augeas.rb +++ b/lib/puppet/provider/augeas/augeas.rb @@ -147,7 +147,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do flags = Augeas::TYPE_CHECK if resource[:type_check] == :true flags |= Augeas::NO_MODL_AUTOLOAD if resource[:incl] root = resource[:root] - load_path = resource[:load_path] + load_path = get_load_path(resource) debug("Opening augeas with root #{root}, lens path #{load_path}, flags #{flags}") @aug = Augeas::open(root, load_path,flags) @@ -253,6 +253,24 @@ Puppet::Type.type(:augeas).provide(:augeas) do !!return_value end + # Generate lens load paths from user given paths and local pluginsync dir + def get_load_path(resource) + load_path = [] + + # Permits colon separated strings or arrays + if resource[:load_path] + load_path = [resource[:load_path]].flatten + load_path.map! { |path| path.split(/:/) } + load_path.flatten! + end + + if File.exists?("#{Puppet[:libdir]}/augeas/lenses") + load_path << "#{Puppet[:libdir]}/augeas/lenses" + end + + load_path.join(":") + end + def get_augeas_version @aug.get("/augeas/version") || "" end diff --git a/lib/puppet/provider/confine.rb b/lib/puppet/provider/confine.rb index 6825def7e..b28d07df3 100644 --- a/lib/puppet/provider/confine.rb +++ b/lib/puppet/provider/confine.rb @@ -25,7 +25,7 @@ class Puppet::Provider::Confine begin require "puppet/provider/confine/#{name}" rescue LoadError => detail - unless detail.to_s =~ /No such file/i + unless detail.to_s =~ /No such file|cannot load such file/i warn "Could not load confine test '#{name}': #{detail}" end # Could not find file diff --git a/lib/puppet/provider/package/msi.rb b/lib/puppet/provider/package/msi.rb index 86b5eacdc..575d4562a 100644 --- a/lib/puppet/provider/package/msi.rb +++ b/lib/puppet/provider/package/msi.rb @@ -4,89 +4,135 @@ Puppet::Type.type(:package).provide(:msi, :parent => Puppet::Provider::Package) desc "Windows package management by installing and removing MSIs. This provider requires a `source` attribute, and will accept paths to local - files or files on mapped drives. - - This provider cannot uninstall arbitrary MSI packages; it can only uninstall - packages which were originally installed by Puppet." + files, mapped drives, or UNC paths." confine :operatingsystem => :windows defaultfor :operatingsystem => :windows + has_feature :installable + has_feature :uninstallable has_feature :install_options - # This is just here to make sure we can find it, and fail if we - # can't. Unfortunately, we need to do "special" quoting of the - # install options or msiexec.exe won't know what to do with them, if - # the value contains a space. - commands :msiexec => "msiexec.exe" + class MsiPackage + extend Enumerable - def self.instances - Dir.entries(installed_listing_dir).reject {|d| d == '.' or d == '..'}.collect do |name| - new(:name => File.basename(name, '.yml'), :provider => :msi, :ensure => :installed) + # From msi.h + INSTALLSTATE_DEFAULT = 5 # product is installed for the current user + INSTALLUILEVEL_NONE = 2 # completely silent installation + + def self.installer + require 'win32ole' + WIN32OLE.new("WindowsInstaller.Installer") + end + + def self.each(&block) + inst = installer + inst.UILevel = INSTALLUILEVEL_NONE + + inst.Products.each do |guid| + # products may be advertised, installed in a different user + # context, etc, we only want to know about products currently + # installed in our context. + next unless inst.ProductState(guid) == INSTALLSTATE_DEFAULT + + package = { + :name => inst.ProductInfo(guid, 'ProductName'), + # although packages have a version, the provider isn't versionable, + # so we can't return a version + # :ensure => inst.ProductInfo(guid, 'VersionString'), + :ensure => :installed, + :provider => :msi, + :productcode => guid, + :packagecode => inst.ProductInfo(guid, 'PackageCode') + } + + yield package + end end end + # Get an array of provider instances for currently installed packages + def self.instances + MsiPackage.enum_for.map { |package| new(package) } + end + + # Find first package whose PackageCode, e.g. {B2BE95D2-CD2C-46D6-8D27-35D150E58EC9}, + # matches the resource name (case-insensitively due to hex) or the ProductName matches + # the resource name. The ProductName is not guaranteed to be unique, but the PackageCode + # should be if the package is authored correctly. def query - {:name => resource[:name], :ensure => :installed} if FileTest.exists?(state_file) + MsiPackage.enum_for.find do |package| + resource[:name].casecmp(package[:packagecode]) == 0 || resource[:name] == package[:name] + end end def install - properties_for_command = nil - if resource[:install_options] - properties_for_command = resource[:install_options].collect do |k,v| - property = shell_quote k - value = shell_quote v - - "#{property}=#{value}" - end - end + fail("The source parameter is required when using the MSI provider.") unless resource[:source] # Unfortunately, we can't use the msiexec method defined earlier, # because of the special quoting we need to do around the MSI # properties to use. - execute ['msiexec.exe', '/qn', '/norestart', '/i', shell_quote(msi_source), properties_for_command].flatten.compact.join(' ') - - File.open(state_file, 'w') do |f| - metadata = { - 'name' => resource[:name], - 'install_options' => resource[:install_options], - 'source' => msi_source - } + command = ['msiexec.exe', '/qn', '/norestart', '/i', shell_quote(resource[:source]), install_options].flatten.compact.join(' ') + execute(command, :combine => true) - f.puts(YAML.dump(metadata)) - end + check_result(exit_status) end def uninstall - msiexec '/qn', '/norestart', '/x', msi_source + fail("The productcode property is missing.") unless properties[:productcode] - File.delete state_file - end + command = ['msiexec.exe', '/qn', '/norestart', '/x', properties[:productcode]].flatten.compact.join(' ') + execute(command, :combine => true) - def validate_source(value) - fail("The source parameter cannot be empty when using the MSI provider.") if value.empty? + check_result(exit_status) end - private - - def msi_source - resource[:source] ||= YAML.load_file(state_file)['source'] rescue nil - - fail("The source parameter is required when using the MSI provider.") unless resource[:source] + def exit_status + $CHILD_STATUS.exitstatus + end - resource[:source] + # http://msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx + ERROR_SUCCESS = 0 + ERROR_SUCCESS_REBOOT_INITIATED = 1641 + ERROR_SUCCESS_REBOOT_REQUIRED = 3010 + + # (Un)install may "fail" because the package requested a reboot, the system requested a + # reboot, or something else entirely. Reboot requests mean the package was installed + # successfully, but we warn since we don't have a good reboot strategy. + def check_result(hr) + operation = resource[:ensure] == :absent ? 'uninstall' : 'install' + + case hr + when ERROR_SUCCESS + # yeah + when 194 + warning("The package requested a reboot to finish the operation.") + when ERROR_SUCCESS_REBOOT_INITIATED + warning("The package #{operation}ed successfully and the system is rebooting now.") + when ERROR_SUCCESS_REBOOT_REQUIRED + warning("The package #{operation}ed successfully, but the system must be rebooted.") + else + raise Puppet::Util::Windows::Error.new("Failed to #{operation}", hr) + end end - def self.installed_listing_dir - listing_dir = File.join(Puppet[:vardir], 'db', 'package', 'msi') + def validate_source(value) + fail("The source parameter cannot be empty when using the MSI provider.") if value.empty? + end - FileUtils.mkdir_p listing_dir unless File.directory? listing_dir + def install_options + # properties is a string delimited by spaces, so each key value must be quoted + properties_for_command = nil + if resource[:install_options] + properties_for_command = resource[:install_options].collect do |k,v| + property = shell_quote k + value = shell_quote v - listing_dir - end + "#{property}=#{value}" + end + end - def state_file - File.join(self.class.installed_listing_dir, "#{resource[:name]}.yml") + properties_for_command end def shell_quote(value) diff --git a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb index 3e8f2bc9b..b9491294d 100644 --- a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +++ b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb @@ -232,6 +232,7 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do unless resource[:ensure] == :absent self.fail('Parameter command is required.') unless resource[:command] task.save + @task = nil end end diff --git a/lib/puppet/provider/service/gentoo.rb b/lib/puppet/provider/service/gentoo.rb index 4beb9ea6c..46e41e23c 100644 --- a/lib/puppet/provider/service/gentoo.rb +++ b/lib/puppet/provider/service/gentoo.rb @@ -12,8 +12,6 @@ Puppet::Type.type(:service).provide :gentoo, :parent => :init do confine :operatingsystem => :gentoo - defaultfor :operatingsystem => :gentoo - def self.defpath superclass.defpath end diff --git a/lib/puppet/provider/service/openrc.rb b/lib/puppet/provider/service/openrc.rb new file mode 100644 index 000000000..a59f1d304 --- /dev/null +++ b/lib/puppet/provider/service/openrc.rb @@ -0,0 +1,69 @@ +# Gentoo OpenRC +Puppet::Type.type(:service).provide :openrc, :parent => :base do + desc <<-EOT + Support for Gentoo's OpenRC initskripts + + Uses rc-update, rc-status and rc-service to manage services. + + EOT + + defaultfor :operatingsystem => :gentoo + defaultfor :operatingsystem => :funtoo + + commands :rcservice => '/sbin/rc-service' + commands :rcstatus => '/bin/rc-status' + commands :rcupdate => '/sbin/rc-update' + + self::STATUSLINE = /^\s+(.*?)\s*\[\s*(.*)\s*\]$/ + + def enable + rcupdate('-C', :add, @resource[:name]) + end + + def disable + rcupdate('-C', :del, @resource[:name]) + end + + # rc-status -a shows all runlevels and dynamic runlevels which + # are not considered as enabled. We have to find out under which + # runlevel our service is listed + def enabled? + enabled = :false + rcstatus('-C', '-a').each_line do |line| + case line.chomp + when /^Runlevel: / + enabled = :true + when /^\S+/ # caption of a dynamic runlevel + enabled = :false + when self.class::STATUSLINE + return enabled if @resource[:name] == $1 + end + end + :false + end + + def self.instances + instances = [] + rcservice('-C', '--list').each_line do |line| + instances << new(:name => line.chomp) + end + instances + end + + def restartcmd + (@resource[:hasrestart] == :true) && [command(:rcservice), @resource[:name], :restart] + end + + def startcmd + [command(:rcservice), @resource[:name], :start ] + end + + def stopcmd + [command(:rcservice), @resource[:name], :stop] + end + + def statuscmd + ((@resource.provider.get(:hasstatus) == true) || (@resource[:hasstatus] == :true)) && [command(:rcservice), @resource[:name], :status] + end + +end diff --git a/lib/puppet/provider/service/windows.rb b/lib/puppet/provider/service/windows.rb index 717e585fd..d8ba69961 100644 --- a/lib/puppet/provider/service/windows.rb +++ b/lib/puppet/provider/service/windows.rb @@ -18,6 +18,8 @@ Puppet::Type.type(:service).provide :windows do has_feature :refreshable + commands :net => 'net.exe' + def enable w32ss = Win32::Service.configure( 'service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_AUTO_START ) raise Puppet::Error.new("Win32 service enable of #{@resource[:name]} failed" ) if( w32ss.nil? ) @@ -73,14 +75,14 @@ Puppet::Type.type(:service).provide :windows do end end - Win32::Service.start( @resource[:name] ) - rescue Win32::Service::Error => detail + net(:start, @resource[:name]) + rescue Puppet::ExecutionFailure => detail raise Puppet::Error.new("Cannot start #{@resource[:name]}, error was: #{detail}" ) end def stop - Win32::Service.stop( @resource[:name] ) - rescue Win32::Service::Error => detail + net(:stop, @resource[:name]) + rescue Puppet::ExecutionFailure => detail raise Puppet::Error.new("Cannot stop #{@resource[:name]}, error was: #{detail}" ) end diff --git a/lib/puppet/provider/user/aix.rb b/lib/puppet/provider/user/aix.rb index ce0b8a3b8..6c9679d8e 100755 --- a/lib/puppet/provider/user/aix.rb +++ b/lib/puppet/provider/user/aix.rb @@ -253,12 +253,16 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do tmpfile.close() # Options '-e', '-c', use encrypted password and clear flags - # Must receibe "user:enc_password" as input + # Must receive "user:enc_password" as input # command, arguments = {:failonfail => true, :combine => true} - cmd = [self.class.command(:chpasswd),"-R", self.class.ia_module, - '-e', '-c', user] + # Fix for bugs #11200 and #10915 + cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c', user].flatten begin - execute(cmd, {:failonfail => true, :combine => true, :stdinfile => tmpfile.path }) + output = execute(cmd, {:failonfail => false, :combine => true, :stdinfile => tmpfile.path }) + # chpasswd can return 1, even on success (at least on AIX 6.1); empty output indicates success + if output != "" + raise Puppet::ExecutionFailure, "chpasswd said #{output}" + end rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}" ensure diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb index e3749057f..c44c19a3a 100644 --- a/lib/puppet/provider/user/useradd.rb +++ b/lib/puppet/provider/user/useradd.rb @@ -75,6 +75,12 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ cmd += check_system_users cmd << @resource[:name] end + + def deletecmd + cmd = [command(:delete)] + cmd += @resource.managehome? ? ['-r'] : [] + cmd << @resource[:name] + end def passcmd age_limits = [:password_min_age, :password_max_age].select { |property| @resource.should(property) } diff --git a/lib/puppet/rails/benchmark.rb b/lib/puppet/rails/benchmark.rb index e1e92bb79..741b6d5bd 100644 --- a/lib/puppet/rails/benchmark.rb +++ b/lib/puppet/rails/benchmark.rb @@ -1,4 +1,6 @@ require 'benchmark' +require 'yaml' + module Puppet::Rails::Benchmark $benchmarks = {:accumulated => {}} @@ -50,8 +52,6 @@ module Puppet::Rails::Benchmark file = "/tmp/time_debugging.yaml" - require 'yaml' - if FileTest.exist?(file) data = YAML.load_file(file) else diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb index 4f2d22532..21dfa2d25 100644 --- a/lib/puppet/reports/store.rb +++ b/lib/puppet/reports/store.rb @@ -13,11 +13,7 @@ Puppet::Reports.register_report(:store) do default report)." def process - # We don't want any tracking back in the fs. Unlikely, but there - # you go. - if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/) - raise ArgumentError, "Invalid node name #{host.inspect}" - end + validate_host(host) dir = File.join(Puppet[:reportdir], host) @@ -55,9 +51,7 @@ Puppet::Reports.register_report(:store) do # removes all reports for a given host? def self.destroy(host) - if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/) - raise ArgumentError, "Invalid node name #{host.inspect}" - end + validate_host(host) dir = File.join(Puppet[:reportdir], host) @@ -70,5 +64,11 @@ Puppet::Reports.register_report(:store) do Dir.rmdir(dir) end end -end + def validate_host(host) + if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/) + raise ArgumentError, "Invalid node name #{host.inspect}" + end + end + module_function :validate_host +end diff --git a/lib/puppet/resource/catalog.rb b/lib/puppet/resource/catalog.rb index 3dcf19c7a..eda5ed8f5 100644 --- a/lib/puppet/resource/catalog.rb +++ b/lib/puppet/resource/catalog.rb @@ -400,7 +400,8 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph # references to the resource instances. def remove_resource(*resources) resources.each do |resource| - @resource_table.delete(resource.ref) + title_key = title_key_for_ref(resource.ref) + @resource_table.delete(title_key) if aliases = @aliases[resource.ref] aliases.each { |res_alias| @resource_table.delete(res_alias) } @aliases.delete(resource.ref) diff --git a/lib/puppet/resource/type_collection.rb b/lib/puppet/resource/type_collection.rb index 89b0a16ed..e432d52a0 100644 --- a/lib/puppet/resource/type_collection.rb +++ b/lib/puppet/resource/type_collection.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/type_loader' + class Puppet::Resource::TypeCollection attr_reader :environment attr_accessor :parse_failed @@ -68,7 +70,6 @@ class Puppet::Resource::TypeCollection end def loader - require 'puppet/parser/type_loader' @loader ||= Puppet::Parser::TypeLoader.new(environment) end diff --git a/lib/puppet/ssl/base.rb b/lib/puppet/ssl/base.rb index 25fd70ca2..f44649016 100644 --- a/lib/puppet/ssl/base.rb +++ b/lib/puppet/ssl/base.rb @@ -1,3 +1,4 @@ +require 'openssl/digest' require 'puppet/ssl' # The base class for wrapping SSL instances. @@ -63,8 +64,6 @@ class Puppet::SSL::Base end def fingerprint(md = :MD5) - require 'openssl/digest' - # ruby 1.8.x openssl digest constants are string # but in 1.9.x they are symbols mds = md.to_s.upcase diff --git a/lib/puppet/ssl/certificate_authority/interface.rb b/lib/puppet/ssl/certificate_authority/interface.rb index 775b7b0c2..6d4114c41 100644 --- a/lib/puppet/ssl/certificate_authority/interface.rb +++ b/lib/puppet/ssl/certificate_authority/interface.rb @@ -28,6 +28,7 @@ module Puppet rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not call #{method}: #{detail}" + raise end end diff --git a/lib/puppet/test/test_helper.rb b/lib/puppet/test/test_helper.rb index 8a3648348..9a05b4db3 100644 --- a/lib/puppet/test/test_helper.rb +++ b/lib/puppet/test/test_helper.rb @@ -79,6 +79,7 @@ module Puppet::Test Puppet[:req_bits] = 512 Puppet[:keylength] = 512 + Puppet.clear_deprecation_warnings end # Call this method once per test, after execution of each individual test. @@ -135,4 +136,4 @@ module Puppet::Test end private_class_method :clear_settings_after_each end -end
\ No newline at end of file +end diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index e41666570..8d0e586b9 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -503,7 +503,7 @@ class Type if provider and ! provider.class.supports_parameter?(klass) missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) } - info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] + debug "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] return nil end diff --git a/lib/puppet/type/augeas.rb b/lib/puppet/type/augeas.rb index cc2ca6b1d..ef075c326 100644 --- a/lib/puppet/type/augeas.rb +++ b/lib/puppet/type/augeas.rb @@ -149,7 +149,7 @@ Puppet::Type.newtype(:augeas) do end newparam(:load_path) do - desc "Optional colon-separated list of directories; these directories are searched for schema definitions." + desc "Optional colon-separated list or array of directories; these directories are searched for schema definitions. The agent's `$libdir/augeas/lenses` path will always be added to support pluginsync." defaultto "" end diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb index d01eee355..dd13c6872 100644 --- a/lib/puppet/type/file.rb +++ b/lib/puppet/type/file.rb @@ -202,7 +202,7 @@ Puppet::Type.newtype(:file) do whose content doesn't match what the `source` or `content` attribute specifies. Setting this to false allows file resources to initialize files without overwriting future changes. Note that this only affects content; - Puppet will still manage ownership and permissions." + Puppet will still manage ownership and permissions. Defaults to `true`." newvalues(:true, :false) aliasvalue(:yes, :true) aliasvalue(:no, :false) @@ -437,7 +437,7 @@ Puppet::Type.newtype(:file) do # from it. unless self[:ensure] if self[:target] - self[:ensure] = :symlink + self[:ensure] = :link elsif self[:content] self[:ensure] = :file end @@ -724,6 +724,8 @@ Puppet::Type.newtype(:file) do ::File.send(method, self[:path]) rescue Errno::ENOENT => error nil + rescue Errno::ENOTDIR => error + nil rescue Errno::EACCES => error warning "Could not stat; permission denied" nil diff --git a/lib/puppet/type/scheduled_task.rb b/lib/puppet/type/scheduled_task.rb index 4a0fe4e66..1be367f63 100644 --- a/lib/puppet/type/scheduled_task.rb +++ b/lib/puppet/type/scheduled_task.rb @@ -33,6 +33,12 @@ Puppet::Type.newtype(:scheduled_task) do validate do |value| raise Puppet::Error.new('Must be specified using an absolute path.') unless absolute_path?(value) end + munge do |value| + # windows converts slashes to backslashes, so the *is* value + # has backslashes. Do the same for the *should* value, so that + # we are slash-insensitive. See #13009 + File.expand_path(value).gsub(/\//, '\\') + end end newproperty(:working_dir) do @@ -43,9 +49,9 @@ Puppet::Type.newtype(:scheduled_task) do end end - newproperty(:arguments, :array_matching => :all) do + newproperty(:arguments) do desc "Any arguments or flags that should be passed to the command. Multiple arguments - can be specified as an array or as a space-separated string." + should be specified as a space-separated string." end newproperty(:user) do @@ -157,12 +163,4 @@ Puppet::Type.newtype(:scheduled_task) do self.class.format_value_for_display(current_value) end end - - validate do - return true if self[:ensure] == :absent - - if self[:arguments] and !(self[:arguments].is_a?(Array) and self[:arguments].length == 1) - self.fail('Parameter arguments failed: Must be specified as a single string') - end - end end diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb index 224e79731..80e0f9018 100755 --- a/lib/puppet/type/tidy.rb +++ b/lib/puppet/type/tidy.rb @@ -187,7 +187,7 @@ Puppet::Type.newtype(:tidy) do end newparam(:type) do - desc "Set the mechanism for determining age." + desc "Set the mechanism for determining age. Default: atime." newvalues(:atime, :mtime, :ctime) diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index 5b5a9d79d..cad1eb8db 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -9,6 +9,7 @@ require 'sync' require 'monitor' require 'tempfile' require 'pathname' +require 'ostruct' require 'puppet/util/platform' module Puppet @@ -417,11 +418,13 @@ module Util # well. 2.times do |try| if File.exists?(stdout.path) - output = stdout.open.read - - stdout.close(true) - - return output + stdout.open + begin + return stdout.read + ensure + stdout.close + stdout.unlink + end else time_to_sleep = try / 2.0 Puppet.warning "Waiting for output; will sleep #{time_to_sleep} seconds" @@ -521,34 +524,31 @@ module Util # across. def replace_file(file, default_mode, &block) raise Puppet::DevError, "replace_file requires a block" unless block_given? - raise Puppet::DevError, "replace_file is non-functional on Windows" if Puppet.features.microsoft_windows? file = Pathname(file) tempfile = Tempfile.new(file.basename.to_s, file.dirname.to_s) file_exists = file.exist? - # If the file exists, use its current mode/owner/group. If it doesn't, use - # the supplied mode, and default to current user/group. - if file_exists - stat = file.lstat - - # We only care about the four lowest-order octets. Higher octets are - # filesystem-specific. - mode = stat.mode & 07777 - uid = stat.uid - gid = stat.gid - else - mode = default_mode - uid = Process.euid - gid = Process.egid - end - # Set properties of the temporary file before we write the content, because # Tempfile doesn't promise to be safe from reading by other people, just # that it avoids races around creating the file. - tempfile.chmod(mode) - tempfile.chown(uid, gid) + # + # Our Windows emulation is pretty limited, and so we have to carefully + # and specifically handle the platform, which has all sorts of magic. + # So, unlike Unix, we don't pre-prep security; we use the default "quite + # secure" tempfile permissions instead. Magic happens later. + unless Puppet.features.microsoft_windows? + # Grab the current file mode, and fall back to the defaults. + stat = file.lstat rescue OpenStruct.new(:mode => default_mode, + :uid => Process.euid, + :gid => Process.egid) + + # We only care about the bottom four slots, which make the real mode, + # and not the rest of the platform stat call fluff and stuff. + tempfile.chmod(stat.mode & 07777) + tempfile.chown(stat.uid, stat.gid) + end # OK, now allow the caller to write the content of the file. yield tempfile @@ -569,7 +569,45 @@ module Util tempfile.close - File.rename(tempfile.path, file) + if Puppet.features.microsoft_windows? + # This will appropriately clone the file, but only if the file we are + # replacing exists. Which is kind of annoying; thanks Microsoft. + # + # So, to avoid getting into an infinite loop we will retry once if the + # file doesn't exist, but only the once... + have_retried = false + + begin + # Yes, the arguments are reversed compared to the rename in the rest + # of the world. + Puppet::Util::Windows::File.replace_file(file, tempfile.path) + rescue Puppet::Util::Windows::Error => e + # This might race, but there are enough possible cases that there + # isn't a good, solid "better" way to do this, and the next call + # should fail in the same way anyhow. + raise if have_retried or File.exist?(file) + have_retried = true + + # OK, so, we can't replace a file that doesn't exist, so let us put + # one in place and set the permissions. Then we can retry and the + # magic makes this all work. + # + # This is the least-worst option for handling Windows, as far as we + # can determine. + File.open(file, 'a') do |fh| + # this space deliberately left empty for auto-close behaviour, + # append mode, and not actually changing any of the content. + end + + # Set the permissions to what we want. + Puppet::Util::Windows::Security.set_mode(default_mode, file.to_s) + + # ...and finally retry the operation. + retry + end + else + File.rename(tempfile.path, file) + end # Ideally, we would now fsync the directory as well, but Ruby doesn't # have support for that, and it doesn't matter /that/ much... diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb index 8051d01af..f20f16a79 100644 --- a/lib/puppet/util/autoload.rb +++ b/lib/puppet/util/autoload.rb @@ -107,8 +107,8 @@ class Puppet::Util::Autoload name = File.basename(file).chomp(".rb").intern next if loaded?(name) begin - Kernel.require file loaded(name, file) + Kernel.require file rescue SystemExit,NoMemoryError raise rescue Exception => detail @@ -128,9 +128,11 @@ class Puppet::Util::Autoload end def module_directories(env=nil) - # We have to require this late in the process because otherwise we might have - # load order issues. - require 'puppet/node/environment' + # We have to require this late in the process because otherwise we might + # have load order issues. Since require is much slower than defined?, we + # can skip that - and save some 2,155 invocations of require in my real + # world testing. --daniel 2012-07-10 + require 'puppet/node/environment' unless defined?(Puppet::Node::Environment) real_env = Puppet::Node::Environment.new(env) diff --git a/lib/puppet/util/checksums.rb b/lib/puppet/util/checksums.rb index dd90caa5f..a505bfc72 100644 --- a/lib/puppet/util/checksums.rb +++ b/lib/puppet/util/checksums.rb @@ -1,3 +1,6 @@ +require 'digest/md5' +require 'digest/sha1' + # A stand-alone module for calculating checksums # in a generic way. module Puppet::Util::Checksums @@ -24,7 +27,6 @@ module Puppet::Util::Checksums # Calculate a checksum using Digest::MD5. def md5(content) - require 'digest/md5' Digest::MD5.hexdigest(content) end @@ -35,8 +37,6 @@ module Puppet::Util::Checksums # Calculate a checksum of a file's content using Digest::MD5. def md5_file(filename, lite = false) - require 'digest/md5' - digest = Digest::MD5.new checksum_file(digest, filename, lite) end @@ -47,7 +47,6 @@ module Puppet::Util::Checksums end def md5_stream(&block) - require 'digest/md5' digest = Digest::MD5.new yield digest digest.hexdigest @@ -74,7 +73,6 @@ module Puppet::Util::Checksums # Calculate a checksum using Digest::SHA1. def sha1(content) - require 'digest/sha1' Digest::SHA1.hexdigest(content) end @@ -85,8 +83,6 @@ module Puppet::Util::Checksums # Calculate a checksum of a file's content using Digest::SHA1. def sha1_file(filename, lite = false) - require 'digest/sha1' - digest = Digest::SHA1.new checksum_file(digest, filename, lite) end @@ -97,7 +93,6 @@ module Puppet::Util::Checksums end def sha1_stream - require 'digest/sha1' digest = Digest::SHA1.new yield digest digest.hexdigest diff --git a/lib/puppet/util/diff.rb b/lib/puppet/util/diff.rb index b8bbbe6af..fa20de1b9 100644 --- a/lib/puppet/util/diff.rb +++ b/lib/puppet/util/diff.rb @@ -1,3 +1,5 @@ +require 'tempfile' + # Provide a diff between two strings. module Puppet::Util::Diff include Puppet::Util @@ -64,7 +66,6 @@ module Puppet::Util::Diff end def string_file_diff(path, string) - require 'tempfile' tempfile = Tempfile.new("puppet-diffing") tempfile.open tempfile.print string diff --git a/lib/puppet/util/filetype.rb b/lib/puppet/util/filetype.rb index fdc6ccd9b..51b0d9175 100755 --- a/lib/puppet/util/filetype.rb +++ b/lib/puppet/util/filetype.rb @@ -2,6 +2,7 @@ # to see here. require 'puppet/util/selinux' +require 'tempfile' require 'fileutils' class Puppet::Util::FileType @@ -103,7 +104,6 @@ class Puppet::Util::FileType # Overwrite the file. def write(text) - require "tempfile" tf = Tempfile.new("puppet") tf.print text; tf.flush FileUtils.cp(tf.path, @path) @@ -223,7 +223,6 @@ class Puppet::Util::FileType # and the text with which to create the cron tab. def write(text) puts text - require "tempfile" output_file = Tempfile.new("puppet") fh = output_file.open fh.print text @@ -262,7 +261,6 @@ class Puppet::Util::FileType # Overwrite a specific @path's cron tab; must be passed the @path name # and the text with which to create the cron tab. def write(text) - require "tempfile" output_file = Tempfile.new("puppet") fh = output_file.open fh.print text diff --git a/lib/puppet/util/run_mode.rb b/lib/puppet/util/run_mode.rb index 6028aef29..5395a8ef9 100644 --- a/lib/puppet/util/run_mode.rb +++ b/lib/puppet/util/run_mode.rb @@ -1,3 +1,5 @@ +require 'etc' + module Puppet module Util class RunMode @@ -71,7 +73,6 @@ module Puppet end def expand_path( dir ) - require 'etc' ENV["HOME"] ||= Etc.getpwuid(Process.uid).dir File.expand_path(dir) end diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb index f270c40e2..513078d34 100644 --- a/lib/puppet/util/suidmanager.rb +++ b/lib/puppet/util/suidmanager.rb @@ -1,3 +1,4 @@ +require 'facter' require 'puppet/util/warnings' require 'forwardable' require 'etc' @@ -17,7 +18,6 @@ module Puppet::Util::SUIDManager def osx_maj_ver return @osx_maj_ver unless @osx_maj_ver.nil? - require 'facter' # 'kernel' is available without explicitly loading all facts if Facter.value('kernel') != 'Darwin' @osx_maj_ver = false diff --git a/lib/puppet/util/windows.rb b/lib/puppet/util/windows.rb index 086e08c21..50968671f 100644 --- a/lib/puppet/util/windows.rb +++ b/lib/puppet/util/windows.rb @@ -3,4 +3,5 @@ module Puppet::Util::Windows require 'puppet/util/windows/security' require 'puppet/util/windows/user' require 'puppet/util/windows/process' + require 'puppet/util/windows/file' end diff --git a/lib/puppet/util/windows/file.rb b/lib/puppet/util/windows/file.rb new file mode 100644 index 000000000..d4b7bc1ca --- /dev/null +++ b/lib/puppet/util/windows/file.rb @@ -0,0 +1,27 @@ +require 'puppet/util/windows' + +module Puppet::Util::Windows::File + require 'windows/api' + require 'windows/wide_string' + + ReplaceFileWithoutBackupW = Windows::API.new('ReplaceFileW', 'PPVLVV', 'B') + def replace_file(target, source) + result = ReplaceFileWithoutBackupW.call(WideString.new(target.to_s), + WideString.new(source.to_s), + 0, 0x1, 0, 0) + return true unless result == 0 + raise Puppet::Util::Windows::Error.new("ReplaceFile(#{target}, #{source})") + end + module_function :replace_file + + MoveFileEx = Windows::API.new('MoveFileExW', 'PPL', 'B') + def move_file_ex(source, target, flags = 0) + result = MoveFileEx.call(WideString.new(source.to_s), + WideString.new(target.to_s), + flags) + return true unless result == 0 + raise Puppet::Util::Windows::Error. + new("MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})") + end + module_function :move_file_ex +end diff --git a/lib/puppet/util/windows/user.rb b/lib/puppet/util/windows/user.rb index 6722a0e2e..0f3232369 100644 --- a/lib/puppet/util/windows/user.rb +++ b/lib/puppet/util/windows/user.rb @@ -1,14 +1,13 @@ require 'puppet/util/windows' require 'win32/security' +require 'facter' module Puppet::Util::Windows::User include Windows::Security extend Windows::Security def admin? - require 'facter' - majversion = Facter.value(:kernelmajversion) return false unless majversion diff --git a/man/man8/puppet-agent.8 b/man/man8/puppet-agent.8 index 4d36fba5e..35a5ce06c 100644 --- a/man/man8/puppet-agent.8 +++ b/man/man8/puppet-agent.8 @@ -147,6 +147,10 @@ Shut down the puppet agent daemon\. SIGUSR1 Immediately retrieve and apply configurations from the puppet master\. . +.TP +SIGUSR2 +Close file descriptors for log files and reopen them\. Used with logrotate\. +. .SH "AUTHOR" Luke Kanies . diff --git a/man/man8/puppet-master.8 b/man/man8/puppet-master.8 index c91ad0605..cf27179ea 100644 --- a/man/man8/puppet-master.8 +++ b/man/man8/puppet-master.8 @@ -67,6 +67,10 @@ Restart the puppet master server\. SIGINT and SIGTERM Shut down the puppet master server\. . +.TP +SIGUSR2 +Close file descriptors for log files and reopen them\. Used with logrotate\. +. .SH "AUTHOR" Luke Kanies . diff --git a/man/man8/puppetmasterd.8 b/man/man8/puppetmasterd.8 index c91ad0605..cf27179ea 100644 --- a/man/man8/puppetmasterd.8 +++ b/man/man8/puppetmasterd.8 @@ -67,6 +67,10 @@ Restart the puppet master server\. SIGINT and SIGTERM Shut down the puppet master server\. . +.TP +SIGUSR2 +Close file descriptors for log files and reopen them\. Used with logrotate\. +. .SH "AUTHOR" Luke Kanies . diff --git a/spec/fixtures/unit/provider/augeas/augeas/augeas/lenses/test.aug b/spec/fixtures/unit/provider/augeas/augeas/augeas/lenses/test.aug new file mode 100644 index 000000000..bea707ea2 --- /dev/null +++ b/spec/fixtures/unit/provider/augeas/augeas/augeas/lenses/test.aug @@ -0,0 +1,13 @@ +(* +Simple lens, written to be distributed with Puppet unit tests. + +Author: Dominic Cleal <dcleal@redhat.com> + +About: License: + This file is licensed under the Apache 2.0 licence, like the rest of Puppet. +*) + +module Test = autoload xfm +let lns = [ seq "line" . store /[^\n]+/ . del "\n" "\n" ]* +let filter = incl "/etc/test" +let xfm = transform lns filter diff --git a/spec/fixtures/unit/provider/augeas/augeas/etc/fstab b/spec/fixtures/unit/provider/augeas/augeas/etc/fstab new file mode 100644 index 000000000..ddbd8ffbd --- /dev/null +++ b/spec/fixtures/unit/provider/augeas/augeas/etc/fstab @@ -0,0 +1,10 @@ +/dev/vg00/lv00 / ext3 defaults 1 1 +LABEL=/boot /boot ext3 defaults 1 2 +devpts /dev/pts devpts gid=5,mode=620 0 0 +tmpfs /dev/shm tmpfs defaults 0 0 +/dev/vg00/home /home ext3 defaults 1 2 +proc /proc proc defaults 0 0 +sysfs /sys sysfs defaults 0 0 +/dev/vg00/local /local ext3 defaults 1 2 +/dev/vg00/images /var/lib/xen/images ext3 defaults 1 2 +/dev/vg00/swap swap swap defaults 0 0 diff --git a/spec/fixtures/unit/provider/augeas/augeas/etc/hosts b/spec/fixtures/unit/provider/augeas/augeas/etc/hosts new file mode 100644 index 000000000..44cd9da21 --- /dev/null +++ b/spec/fixtures/unit/provider/augeas/augeas/etc/hosts @@ -0,0 +1,6 @@ +# Do not remove the following line, or various programs +# that require network functionality will fail. +127.0.0.1 localhost.localdomain localhost galia.watzmann.net galia +#172.31.122.254 granny.watzmann.net granny puppet +#172.31.122.1 galia.watzmann.net galia +172.31.122.14 orange.watzmann.net orange diff --git a/spec/fixtures/unit/provider/augeas/augeas/etc/test b/spec/fixtures/unit/provider/augeas/augeas/etc/test new file mode 100644 index 000000000..86e041dad --- /dev/null +++ b/spec/fixtures/unit/provider/augeas/augeas/etc/test @@ -0,0 +1,3 @@ +foo +bar +baz diff --git a/spec/fixtures/unit/provider/augeas/augeas/test.aug b/spec/fixtures/unit/provider/augeas/augeas/test.aug new file mode 100644 index 000000000..bea707ea2 --- /dev/null +++ b/spec/fixtures/unit/provider/augeas/augeas/test.aug @@ -0,0 +1,13 @@ +(* +Simple lens, written to be distributed with Puppet unit tests. + +Author: Dominic Cleal <dcleal@redhat.com> + +About: License: + This file is licensed under the Apache 2.0 licence, like the rest of Puppet. +*) + +module Test = autoload xfm +let lns = [ seq "line" . store /[^\n]+/ . del "\n" "\n" ]* +let filter = incl "/etc/test" +let xfm = transform lns filter diff --git a/spec/fixtures/unit/provider/service/openrc/rcservice_list b/spec/fixtures/unit/provider/service/openrc/rcservice_list new file mode 100644 index 000000000..f413a566c --- /dev/null +++ b/spec/fixtures/unit/provider/service/openrc/rcservice_list @@ -0,0 +1,8 @@ +alsasound +consolefont +lvm-monitoring +pydoc-2.7 +pydoc-3.2 +wpa_supplicant +xdm +xdm-setup diff --git a/spec/fixtures/unit/provider/service/openrc/rcstatus b/spec/fixtures/unit/provider/service/openrc/rcstatus new file mode 100644 index 000000000..1406671a4 --- /dev/null +++ b/spec/fixtures/unit/provider/service/openrc/rcstatus @@ -0,0 +1,43 @@ +Runlevel: boot + hwclock [ started ] + modules [ started ] + dmcrypt [ started ] + lvm [ started ] + fsck [ started ] + root [ started ] + mtab [ started ] + swap [ started ] + localmount [ started ] + sysctl [ started ] + bootmisc [ started ] + hostname [ started ] + termencoding [ started ] + keymaps [ started ] + net.lo [ started ] + procfs [ started ] + rsyslog [ started ] + swapfiles [ started ] + urandom [ started ] +Runlevel: default + netmount [ started ] + foo_with_very_very_long_servicename_no_still_not_the_end_wait_for_it_almost_there_almost_there_now_finally_the_end [ started ] + xdm [ started ] + alsasound [ started ] + udev-postmount [ started ] + local [ started ] +Runlevel: shutdown + killprocs [ stopped ] + savecache [ stopped ] + mount-ro [ stopped ] +Runlevel: sysinit + dmesg [ started ] + udev [ started ] + devfs [ started ] +Dynamic Runlevel: hotplugged + net.eth0 [ started ] + pcscd [ started ] +Dynamic Runlevel: needed + sysfs [ started ] + udev-mount [ started ] +Dynamic Runlevel: manual + sshd [ started ] diff --git a/spec/integration/defaults_spec.rb b/spec/integration/defaults_spec.rb index 6474ea2e8..6e0b504a2 100755 --- a/spec/integration/defaults_spec.rb +++ b/spec/integration/defaults_spec.rb @@ -18,7 +18,7 @@ describe "Puppet defaults" do describe "when setting the :certname" do it "should fail if the certname is not downcased" do - lambda { Puppet.settings[:certname] = "Host.Domain.Com" }.should raise_error(ArgumentError) + expect { Puppet.settings[:certname] = "Host.Domain.Com" }.to raise_error(ArgumentError) end end @@ -46,7 +46,7 @@ describe "Puppet defaults" do describe "when :certdnsnames is set" do it "should not fail" do - expect { Puppet[:certdnsnames] = 'fred:wilma' }.should_not raise_error + expect { Puppet[:certdnsnames] = 'fred:wilma' }.to_not raise_error end it "should warn the value is ignored" do @@ -300,7 +300,7 @@ describe "Puppet defaults" do end it "should raise an error if set to true" do - lambda { Puppet.settings[:daemonize] = true }.should raise_error(/Cannot daemonize on Windows/) + expect { Puppet.settings[:daemonize] = true }.to raise_error(/Cannot daemonize on Windows/) end end end diff --git a/spec/integration/network/server/mongrel_spec.rb b/spec/integration/network/server/mongrel_spec.rb index a92ba83a1..44f20c30b 100755 --- a/spec/integration/network/server/mongrel_spec.rb +++ b/spec/integration/network/server/mongrel_spec.rb @@ -25,15 +25,16 @@ describe Puppet::Network::Server, :'fails_on_ruby_1.9.2' => true do describe "before listening" do it "should not be reachable at the specified address and port" do - lambda { Net::HTTP.get('127.0.0.1', '/', port) }. - should raise_error(Errno::ECONNREFUSED) + expect { + Net::HTTP.get('127.0.0.1', '/', port) + }.to raise_error(Errno::ECONNREFUSED) end end describe "when listening" do it "should be reachable on the specified address and port" do @server.listen - expect { Net::HTTP.get('127.0.0.1', '/', port) }.should_not raise_error + expect { Net::HTTP.get('127.0.0.1', '/', port) }.to_not raise_error end it "should default to '127.0.0.1' as its bind address" do @@ -54,7 +55,7 @@ describe Puppet::Network::Server, :'fails_on_ruby_1.9.2' => true do it "should not allow multiple servers to listen on the same address and port" do @server.listen @server2 = Puppet::Network::Server.new(@params) - lambda { @server2.listen }.should raise_error + expect { @server2.listen }.to raise_error end end @@ -62,8 +63,9 @@ describe Puppet::Network::Server, :'fails_on_ruby_1.9.2' => true do it "should not be reachable on the port and address assigned" do @server.listen @server.unlisten - expect { Net::HTTP.get('127.0.0.1', '/', port) }. - should raise_error Errno::ECONNREFUSED + expect { + Net::HTTP.get('127.0.0.1', '/', port) + }.to raise_error Errno::ECONNREFUSED end end end diff --git a/spec/integration/parser/parser_spec.rb b/spec/integration/parser/parser_spec.rb index f6abdb274..06607eec0 100755 --- a/spec/integration/parser/parser_spec.rb +++ b/spec/integration/parser/parser_spec.rb @@ -119,7 +119,7 @@ describe Puppet::Parser::Parser do end it "should fail if asked to parse '$foo::::bar'" do - expect { @parser.parse("$foo::::bar") }.should raise_error(Puppet::ParseError, /Syntax error at ':'/) + expect { @parser.parse("$foo::::bar") }.to raise_error(Puppet::ParseError, /Syntax error at ':'/) end describe "function calls" do diff --git a/spec/integration/type/file_spec.rb b/spec/integration/type/file_spec.rb index 2f87918a4..1b7b87ced 100755 --- a/spec/integration/type/file_spec.rb +++ b/spec/integration/type/file_spec.rb @@ -14,7 +14,12 @@ describe Puppet::Type.type(:file) do include PuppetSpec::Files let(:catalog) { Puppet::Resource::Catalog.new } - let(:path) { tmpfile('file_testing') } + let(:path) do + # we create a directory first so backups of :path that are stored in + # the same directory will also be removed after the tests + parent = tmpdir('file_spec') + File.join(parent, 'file_testing') + end if Puppet.features.posix? def set_mode(mode, file) @@ -65,11 +70,37 @@ describe Puppet::Type.type(:file) do file.parameter(:mode).expects(:retrieve).never - report = catalog.apply.report - report.resource_statuses["File[#{path}]"].should_not be_failed + status = catalog.apply.report.resource_statuses["File[#{path}]"] + status.should_not be_failed + status.should_not be_changed File.should_not be_exist(path) end + describe "when ensure is absent" do + it "should remove the file if present" do + FileUtils.touch(path) + catalog.add_resource(described_class.new(:path => path, :ensure => :absent, :backup => :false)) + report = catalog.apply.report + report.resource_statuses["File[#{path}]"].should_not be_failed + File.should_not be_exist(path) + end + + it "should do nothing if file is not present" do + catalog.add_resource(described_class.new(:path => path, :ensure => :absent, :backup => :false)) + report = catalog.apply.report + report.resource_statuses["File[#{path}]"].should_not be_failed + File.should_not be_exist(path) + end + + # issue #14599 + it "should not fail if parts of path aren't directories" do + FileUtils.touch(path) + catalog.add_resource(described_class.new(:path => File.join(path,'no_such_file'), :ensure => :absent, :backup => :false)) + report = catalog.apply.report + report.resource_statuses["File[#{File.join(path,'no_such_file')}]"].should_not be_failed + end + end + describe "when setting permissions" do it "should set the owner" do FileUtils.touch(path) @@ -182,14 +213,11 @@ describe Puppet::Type.type(:file) do describe "when managing links" do let(:target) { tmpfile('target') } - before :each do + it "should not set the executable bit on the link nor the target" do FileUtils.touch(target) File.chmod(0444, target) - File.symlink(target, link) - end - it "should not set the executable bit on the link nor the target" do catalog.add_resource described_class.new(:path => link, :ensure => :link, :mode => 0666, :target => target, :links => :manage) catalog.apply @@ -198,13 +226,23 @@ describe Puppet::Type.type(:file) do end it "should ignore dangling symlinks (#6856)" do - File.delete(target) + File.symlink(target, link) catalog.add_resource described_class.new(:path => link, :ensure => :link, :mode => 0666, :target => target, :links => :manage) catalog.apply File.should_not be_exist(link) end + + it "should create a link to the target if ensure is omitted" do + FileUtils.touch(target) + catalog.add_resource described_class.new(:path => link, :target => target) + catalog.apply + + File.should be_exist link + File.lstat(link).ftype.should == 'link' + File.readlink(link).should == target + end end describe "when following links" do @@ -381,8 +419,7 @@ describe Puppet::Type.type(:file) do end it "should fail if no backup can be performed" do - dir = tmpfile("backups") - Dir.mkdir(dir) + dir = tmpdir("backups") file = described_class.new :path => File.join(dir, "testfile"), :backup => ".bak", :content => "foo" catalog.add_resource file @@ -839,8 +876,8 @@ describe Puppet::Type.type(:file) do it "should add each generated resource to the catalog" do catalog.apply do |trans| - catalog.resource(:file, File.join(path, "one")).should be_a(described_class) - catalog.resource(:file, File.join(path, "two")).should be_a(described_class) + catalog.resource(:file, File.join(path, "one")).must be_a(described_class) + catalog.resource(:file, File.join(path, "two")).must be_a(described_class) end end diff --git a/spec/lib/puppet_spec/database.rb b/spec/lib/puppet_spec/database.rb index 2f7c209cd..cb77e5857 100644 --- a/spec/lib/puppet_spec/database.rb +++ b/spec/lib/puppet_spec/database.rb @@ -22,9 +22,11 @@ end # ready to roll with a serious database and all. Cleanup is handled # automatically for you. Nothing to do there. def setup_scratch_database - dir = PuppetSpec::Files.tmpdir('puppet-sqlite') - Puppet[:dbadapter] = 'sqlite3' - Puppet[:dblocation] = (dir + 'storeconfigs.sqlite').to_s + Puppet::Rails.stubs(:database_arguments).returns( + :adapter => 'sqlite3', + :log_level => Puppet[:rails_loglevel], + :database => ':memory:' + ) Puppet[:railslog] = '/dev/null' Puppet::Rails.init end diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb index 5608454b9..3f1d7111e 100755 --- a/spec/lib/puppet_spec/files.rb +++ b/spec/lib/puppet_spec/files.rb @@ -29,7 +29,8 @@ module PuppetSpec::Files end end - def make_absolute(path) + def make_absolute(path) PuppetSpec::Files.make_absolute(path) end + def self.make_absolute(path) path = File.expand_path(path) path[0] = 'c' if Puppet.features.microsoft_windows? path diff --git a/spec/monkey_patches/alias_should_to_must.rb b/spec/monkey_patches/alias_should_to_must.rb index 1a1111799..389ff8247 100755 --- a/spec/monkey_patches/alias_should_to_must.rb +++ b/spec/monkey_patches/alias_should_to_must.rb @@ -1,8 +1,21 @@ require 'rspec' +# This is necessary because the RAL has a 'should' method. class Object - # This is necessary because the RAL has a 'should' - # method. alias :must :should alias :must_not :should_not end + +# ...and this is because we want to make sure we don't ignore that change +# above. Gotta love overwriting functions, but the performance cost at +# runtime is pretty terrible if we don't. +require 'puppet/type' +class Puppet::Type + alias :should_native :should + def should(value) + unless value.is_a? String or value.is_a? Symbol + raise "you need to call .must rather than .should on Puppet::Type instances" + end + should_native(value) + end +end diff --git a/spec/shared_behaviours/file_serving_model.rb b/spec/shared_behaviours/file_serving_model.rb index 4ed6c1977..9c35e2e77 100644 --- a/spec/shared_behaviours/file_serving_model.rb +++ b/spec/shared_behaviours/file_serving_model.rb @@ -4,6 +4,9 @@ shared_examples_for "a file_serving model" do include PuppetSpec::Files describe "#indirection" do + localpath = PuppetSpec::Files.make_absolute("/etc/sudoers") + localurl = "file://" + localpath + before :each do # Never connect to the network, no matter what described_class.indirection.terminus(:rest).class.any_instance.stubs(:find) @@ -15,8 +18,8 @@ shared_examples_for "a file_serving model" do end { - "/etc/sudoers" => :file_server, - "file:///etc/sudoers" => :file_server, + localpath => :file_server, + localurl => :file_server, "puppet:///modules/foo/bar" => :file_server, "puppet://server/modules/foo/bar" => :file_server, }.each do |key, terminus| @@ -36,8 +39,8 @@ shared_examples_for "a file_serving model" do end { - "/etc/sudoers" => :file, - "file:///etc/sudoers" => :file, + localpath => :file, + localurl => :file, "puppet:///modules/foo/bar" => :file_server, "puppet://server/modules/foo/bar" => :rest, }.each do |key, terminus| @@ -57,8 +60,8 @@ shared_examples_for "a file_serving model" do end { - "/etc/sudoers" => :file, - "file:///etc/sudoers" => :file, + localpath => :file, + localurl => :file, "puppet:///modules/foo/bar" => :rest, "puppet://server/modules/foo/bar" => :rest, }.each do |key, terminus| diff --git a/spec/shared_behaviours/path_parameters.rb b/spec/shared_behaviours/path_parameters.rb index 2d195a18e..d5f06875b 100755 --- a/spec/shared_behaviours/path_parameters.rb +++ b/spec/shared_behaviours/path_parameters.rb @@ -46,7 +46,7 @@ shared_examples_for "all pathname parameters with arrays" do |win32| it "should #{reject ? 'reject' : 'accept'} #{set.join(", ")}" do if reject then expect { instance(data) }. - should raise_error Puppet::Error, /fully qualified/ + to raise_error Puppet::Error, /fully qualified/ else instance = instance(data) instance[@param].should == data @@ -56,7 +56,7 @@ shared_examples_for "all pathname parameters with arrays" do |win32| it "should #{reject ? 'reject' : 'accept'} #{set.join(", ")} doubled" do if reject then expect { instance(data + data) }. - should raise_error Puppet::Error, /fully qualified/ + to raise_error Puppet::Error, /fully qualified/ else instance = instance(data + data) instance[@param].should == (data + data) @@ -101,7 +101,7 @@ shared_examples_for "all path parameters" do |param, options| it "should give a useful error when the path is not absolute" do path = 'foo' expect { instance(path) }. - should raise_error Puppet::Error, /fully qualified/ + to raise_error Puppet::Error, /fully qualified/ end { "Unix" => '/', "Win32" => '\\' }.each do |style, slash| @@ -109,7 +109,7 @@ shared_examples_for "all path parameters" do |param, options| it "should reject drive letter '#{drive}' with #{style} path separators" do path = "#{drive}:#{slash}Program Files" expect { instance(path) }. - should raise_error Puppet::Error, /fully qualified/ + to raise_error Puppet::Error, /fully qualified/ end end end @@ -128,7 +128,7 @@ shared_examples_for "all path parameters" do |param, options| it "should give a useful error when the path is not absolute" do path = 'foo' expect { instance(path) }. - should raise_error Puppet::Error, /fully qualified/ + to raise_error Puppet::Error, /fully qualified/ end it "also accepts Unix style path separators" do diff --git a/spec/shared_behaviours/things_that_declare_options.rb b/spec/shared_behaviours/things_that_declare_options.rb index ecdbfcaea..017a5ed78 100755 --- a/spec/shared_behaviours/things_that_declare_options.rb +++ b/spec/shared_behaviours/things_that_declare_options.rb @@ -52,7 +52,7 @@ shared_examples_for "things that declare options" do option "--foo" option "--foo" end - }.should raise_error ArgumentError, /Option foo conflicts with existing option foo/i + }.to raise_error ArgumentError, /Option foo conflicts with existing option foo/i end it "should detect conflicts in short options" do @@ -61,7 +61,7 @@ shared_examples_for "things that declare options" do option "-f" option "-f" end - }.should raise_error ArgumentError, /Option f conflicts with existing option f/ + }.to raise_error ArgumentError, /Option f conflicts with existing option f/ end ["-f", "--foo"].each do |option| @@ -72,7 +72,7 @@ shared_examples_for "things that declare options" do add_options_to do option input, input end - }.should raise_error ArgumentError, /duplicates existing alias/ + }.to raise_error ArgumentError, /duplicates existing alias/ end end end @@ -90,13 +90,13 @@ shared_examples_for "things that declare options" do option *base option *conflict end - }.should raise_error ArgumentError, /conflicts with existing option/ + }.to raise_error ArgumentError, /conflicts with existing option/ end end it "should fail if we are not consistent about taking an argument" do expect { add_options_to do option "--foo=bar", "--bar" end }. - should raise_error ArgumentError, /inconsistent about taking an argument/ + to raise_error ArgumentError, /inconsistent about taking an argument/ end it "should not accept optional arguments" do diff --git a/spec/unit/application/facts_spec.rb b/spec/unit/application/facts_spec.rb index 7a7c36597..4554f4273 100755 --- a/spec/unit/application/facts_spec.rb +++ b/spec/unit/application/facts_spec.rb @@ -21,7 +21,7 @@ describe Puppet::Application::Facts do expect { expect { subject.run }.to exit_with 0 - }.should have_printed(/object:Puppet::Node::Facts/) + }.to have_printed(/object:Puppet::Node::Facts/) @logs.should be_empty end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index b26e8e0b2..ec3c86179 100755 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -32,9 +32,11 @@ describe Puppet::Application do end it "should exit if it can't find a class" do - reg = "Unable to find application 'ThisShallNeverEverEverExist'. " - reg += "no such file to load -- puppet/application/thisshallneverevereverexist" - @klass.expects(:puts).with(reg) + @klass.expects(:puts).with do |value| + value =~ /Unable to find application 'ThisShallNeverEverEverExist'/ and + value =~ /puppet\/application\/thisshallneverevereverexist/ and + value =~ /no such file to load|cannot load such file/ + end expect { @klass.find("ThisShallNeverEverEverExist") }.to exit_with 1 end @@ -80,7 +82,7 @@ describe Puppet::Application do app.class.run_mode.name.should == :agent $puppet_application_mode.name.should == :agent - }.should_not raise_error + }.to_not raise_error Puppet[:run_mode].should == "agent" end @@ -93,7 +95,7 @@ describe Puppet::Application do $puppet_application_mode.name.should == :master app.set_run_mode app.class.run_mode "agent" $puppet_application_mode.name.should == :agent - }.should raise_error + }.to raise_error end it "should explode when an invalid run mode is set at runtime, for great victory" @@ -432,7 +434,7 @@ describe Puppet::Application do it "should not fail if the route file doesn't exist" do Puppet[:route_file] = "/dev/null/non-existent" - expect { @app.configure_indirector_routes }.should_not raise_error + expect { @app.configure_indirector_routes }.to_not raise_error end it "should raise an error if the routes file is invalid" do @@ -443,7 +445,7 @@ describe Puppet::Application do ROUTES end - expect { @app.configure_indirector_routes }.should raise_error + expect { @app.configure_indirector_routes }.to raise_error end end @@ -565,7 +567,7 @@ describe Puppet::Application do raise "I can't believe it, it works!" end - lambda { @app.handle_test2 }.should raise_error + expect { @app.handle_test2 }.to raise_error end it "should declare the option to OptionParser" do diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb index 11f021ef3..e342aefab 100755 --- a/spec/unit/configurer_spec.rb +++ b/spec/unit/configurer_spec.rb @@ -430,9 +430,18 @@ describe Puppet::Configurer do end it "should log but not fail if saving the last run summary fails" do - Puppet::Util::FileLocking.expects(:writelock).raises "exception" + # The mock will raise an exception on any method used. This should + # simulate a nice hard failure from the underlying OS for us. + fh = Class.new(Object) do + def method_missing(*args) + raise "failed to do #{args[0]}" + end + end.new + + Puppet::Util.expects(:replace_file).yields(fh) + Puppet.expects(:err) - lambda { @configurer.save_last_run_summary(@report) }.should_not raise_error + expect { @configurer.save_last_run_summary(@report) }.should_not raise_error end end diff --git a/spec/unit/face/ca_spec.rb b/spec/unit/face/ca_spec.rb index f489fbcb7..2382c151a 100755 --- a/spec/unit/face/ca_spec.rb +++ b/spec/unit/face/ca_spec.rb @@ -40,7 +40,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window :host => 'random-host', :valid => false, :error => 'Could not find a certificate for random-host' } - }.should_not raise_error + }.to_not raise_error end it "should not explode if there is only a CSR" do @@ -50,7 +50,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window :host => 'random-host', :valid => false, :error => 'Could not find a certificate for random-host' } - }.should_not raise_error + }.to_not raise_error end it "should verify a signed certificate" do @@ -69,7 +69,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window :host => 'random-host', :valid => false, :error => 'certificate revoked' } - }.should_not raise_error + }.to_not raise_error end it "should verify a revoked certificate if CRL use was turned off" do @@ -93,14 +93,14 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window it "should not explode if there is no certificate" do expect { subject.fingerprint('random-host').should be_nil - }.should_not raise_error + }.to_not raise_error end it "should fingerprint a CSR" do make_certs('random-host', []) expect { subject.fingerprint('random-host').should =~ /^[0-9A-F:]+$/ - }.should_not raise_error + }.to_not raise_error end it "should fingerprint a certificate" do @@ -128,14 +128,14 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window it "should not explode if there is no certificate" do expect { subject.print('random-host').should be_nil - }.should_not raise_error + }.to_not raise_error end it "should return nothing if there is only a CSR" do make_certs('random-host', []) expect { subject.print('random-host').should be_nil - }.should_not raise_error + }.to_not raise_error end it "should return the certificate content if there is a cert" do @@ -155,7 +155,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window expect { subject.sign('random-host'). should == 'Could not find certificate request for random-host' - }.should_not raise_error + }.to_not raise_error end it "should not explode if there is a signed cert" do @@ -163,7 +163,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window expect { subject.sign('random-host'). should == 'Could not find certificate request for random-host' - }.should_not raise_error + }.to_not raise_error end it "should sign a CSR if one exists" do @@ -216,14 +216,14 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window make_certs('random-host', []) expect { subject.generate('random-host').should =~ /already has a certificate request/ - }.should_not raise_error + }.to_not raise_error end it "should not explode if the certificate with that name already exists" do make_certs([], 'random-host') expect { subject.generate('random-host').should =~ /already has a certificate/ - }.should_not raise_error + }.to_not raise_error end it "should include the specified DNS alt names" do @@ -242,7 +242,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window let :action do Puppet::Face[:ca, '0.1.0'].get_action(:revoke) end it "should not explode when asked to revoke something that doesn't exist" do - expect { subject.revoke('nonesuch') }.should_not raise_error + expect { subject.revoke('nonesuch') }.to_not raise_error end it "should let the user know what went wrong" do @@ -267,7 +267,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window let :action do Puppet::Face[:ca, '0.1.0'].get_action(:destroy) end it "should not explode when asked to delete something that doesn't exist" do - expect { subject.destroy('nonesuch') }.should_not raise_error + expect { subject.destroy('nonesuch') }.to_not raise_error end it "should let the user know if nothing was deleted" do @@ -325,7 +325,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window it "should not fail when a matcher is passed" do expect { subject.list(type.merge :subject => '.').should == [] - }.should_not raise_error + }.to_not raise_error end context "when_rendering :console" do @@ -394,7 +394,7 @@ describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_window else raise "#{action} has arity #{subject.method(action).arity}" end - }.should raise_error(/Not a CA/) + }.to raise_error(/Not a CA/) end end end diff --git a/spec/unit/face/help_spec.rb b/spec/unit/face/help_spec.rb index ef66660ff..b4c74f4d3 100755 --- a/spec/unit/face/help_spec.rb +++ b/spec/unit/face/help_spec.rb @@ -12,20 +12,20 @@ describe Puppet::Face[:help, '0.0.1'] do end it "should accept a call with no arguments" do - expect { subject.help() }.should_not raise_error + expect { subject.help() }.to_not raise_error end it "should accept a face name" do - expect { subject.help(:help) }.should_not raise_error + expect { subject.help(:help) }.to_not raise_error end it "should accept a face and action name" do - expect { subject.help(:help, :help) }.should_not raise_error + expect { subject.help(:help, :help) }.to_not raise_error end it "should fail if more than a face and action are given" do expect { subject.help(:help, :help, :for_the_love_of_god) }. - should raise_error ArgumentError + to raise_error ArgumentError end it "should treat :current and 'current' identically" do @@ -35,7 +35,7 @@ describe Puppet::Face[:help, '0.0.1'] do it "should complain when the request version of a face is missing" do expect { subject.help(:huzzah, :bar, :version => '17.0.0') }. - should raise_error Puppet::Error + to raise_error Puppet::Error end it "should find a face by version" do diff --git a/spec/unit/face/module/install_spec.rb b/spec/unit/face/module/install_spec.rb index ea774daf0..4af874de4 100644 --- a/spec/unit/face/module/install_spec.rb +++ b/spec/unit/face/module/install_spec.rb @@ -88,15 +88,26 @@ describe "puppet module install" do Puppet.settings[:modulepath].should == fakemodpath end + + it "should expand the target directory derived from the modulepath" do + options[:modulepath] = "modules" + expanded_path = File.expand_path("modules") + expected_options.merge!(options) + expected_options[:target_dir] = expanded_path + expected_options[:modulepath] = "modules" + + Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once + subject.install("puppetlabs-apache", options) + end end describe "when target-dir option is passed" do - it "should expand the target directory" do + it "should expand the target directory when target_dir is set" do options[:target_dir] = "modules" expanded_path = File.expand_path("modules") expected_options.merge!(options) expected_options[:target_dir] = expanded_path - expected_options[:modulepath] = "#{expanded_path}#{sep}#{fakemodpath}" + expected_options[:modulepath] = "modules#{sep}#{fakemodpath}" Puppet::ModuleTool::Applications::Installer.expects(:run).with("puppetlabs-apache", expected_options).once subject.install("puppetlabs-apache", options) diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb index b126af6bb..d899c5a61 100755 --- a/spec/unit/face/node_spec.rb +++ b/spec/unit/face/node_spec.rb @@ -48,26 +48,27 @@ describe Puppet::Face[:node, '0.0.1'] do end it "should not accept a call with no arguments" do - expect { subject.clean() }.should raise_error + expect { subject.clean() }.to raise_error end it "should accept a node name" do - expect { subject.clean('hostname') }.should_not raise_error + expect { subject.clean('hostname') }.to_not raise_error end it "should accept more than one node name" do expect do subject.clean('hostname', 'hostname2', {}) - end.should_not raise_error + end.to_not raise_error expect do subject.clean('hostname', 'hostname2', 'hostname3', { :unexport => true }) - end.should_not raise_error + end.to_not raise_error end it "should accept the option --unexport" do - expect { subject.help('hostname', :unexport => true) }. - should_not raise_error ArgumentError + expect { + subject.help('hostname', :unexport => true) + }.to_not raise_error(ArgumentError) end context "clean action" do diff --git a/spec/unit/indirector/certificate_request/ca_spec.rb b/spec/unit/indirector/certificate_request/ca_spec.rb index e5443a26d..3fe8fb3b7 100755 --- a/spec/unit/indirector/certificate_request/ca_spec.rb +++ b/spec/unit/indirector/certificate_request/ca_spec.rb @@ -48,7 +48,7 @@ describe Puppet::SSL::CertificateRequest::Ca, :unless => Puppet.features.microso host.generate_certificate_request @ca.sign(host.name) - expect { Puppet::SSL::Host.indirection.find("bar").generate_certificate_request }.should raise_error(/ignoring certificate request/) + expect { Puppet::SSL::Host.indirection.find("bar").generate_certificate_request }.to raise_error(/ignoring certificate request/) Puppet::SSL::Certificate.indirection.find("bar").name.should == "bar" Puppet::SSL::CertificateRequest.indirection.find("bar").should be_nil diff --git a/spec/unit/indirector/envelope_spec.rb b/spec/unit/indirector/envelope_spec.rb index e056b768c..4f38cc013 100755 --- a/spec/unit/indirector/envelope_spec.rb +++ b/spec/unit/indirector/envelope_spec.rb @@ -8,19 +8,6 @@ describe Puppet::Indirector::Envelope do @instance.extend(Puppet::Indirector::Envelope) end - it "should have an expiration accessor" do - @instance.expiration = "testing" - @instance.expiration.should == "testing" - end - - it "should have an expiration setter" do - @instance.should respond_to(:expiration=) - end - - it "should have a means of testing whether it is expired" do - @instance.should respond_to(:expired?) - end - describe "when testing if it is expired" do it "should return false if there is no expiration set" do @instance.should_not be_expired diff --git a/spec/unit/indirector/facts/inventory_service_spec.rb b/spec/unit/indirector/facts/inventory_service_spec.rb index f44934abc..df6b7ddf5 100644 --- a/spec/unit/indirector/facts/inventory_service_spec.rb +++ b/spec/unit/indirector/facts/inventory_service_spec.rb @@ -16,7 +16,7 @@ describe Puppet::Node::Facts::InventoryService do expect { subject.save(request) - }.should_not raise_error + }.to_not raise_error end end diff --git a/spec/unit/indirector/queue_spec.rb b/spec/unit/indirector/queue_spec.rb index eba136bbc..a27f4b083 100755 --- a/spec/unit/indirector/queue_spec.rb +++ b/spec/unit/indirector/queue_spec.rb @@ -49,7 +49,7 @@ describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do it "should require PSON" do Puppet.features.expects(:pson?).returns false - lambda { @store_class.new }.should raise_error(ArgumentError) + expect { @store_class.new }.to raise_error(ArgumentError) end it 'should use the correct client type and queue' do @@ -75,7 +75,7 @@ describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do it "should catch any exceptions raised" do @store.client.expects(:publish_message).raises ArgumentError - lambda { @store.save(@request) }.should raise_error(Puppet::Error) + expect { @store.save(@request) }.to raise_error(Puppet::Error) end end @@ -110,7 +110,7 @@ describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do it "should log but not propagate errors" do @store_class.client.expects(:subscribe).yields("foo") @store_class.expects(:intern).raises(ArgumentError) - expect { @store_class.subscribe {|o| o } }.should_not raise_error + expect { @store_class.subscribe {|o| o } }.to_not raise_error @logs.length.should == 1 @logs.first.message.should =~ /Error occured with subscription to queue my_queue for indirection my_queue: ArgumentError/ diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb index f18e99a3c..7954baaed 100755 --- a/spec/unit/indirector/rest_spec.rb +++ b/spec/unit/indirector/rest_spec.rb @@ -93,36 +93,47 @@ describe Puppet::Indirector::REST do describe "when making http requests" do include PuppetSpec::Files - it "should provide a suggestive error message when certificate verify failed" do + def a_connection_that_verifies(args) connection = Net::HTTP.new('my_server', 8140) - @searcher.stubs(:network).returns(connection) + connection.stubs(:get).with do + connection.verify_callback.call(args[:has_passed_pre_checks], args[:in_context]) + true + end.raises(OpenSSL::SSL::SSLError.new(args[:fails_with])) + connection + end - connection.stubs(:get).raises(OpenSSL::SSL::SSLError.new('certificate verify failed')) + def a_store_context(args) + Puppet[:confdir] = tmpdir('conf') + cert = Puppet::SSL::CertificateAuthority.new.generate(args[:for_server], :dns_alt_names => args[:for_aliases]).content + ssl_context = mock('OpenSSL::X509::StoreContext') + ssl_context.stubs(:current_cert).returns(cert) + ssl_context.stubs(:error_string).returns(args[:with_error_string]) + ssl_context + end + it "should provide a useful error message when one is available and certificate validation fails", :unless => Puppet.features.microsoft_windows? do + @searcher.stubs(:network). + returns(a_connection_that_verifies(:has_passed_pre_checks => false, + :in_context => a_store_context(:for_server => 'not_my_server', + :with_error_string => 'shady looking signature'), + :fails_with => 'certificate verify failed')) expect do @searcher.http_request(:get, stub('request')) - end.to raise_error(/This is often because the time is out of sync on the server or client/) + end.to raise_error(Puppet::Error, "certificate verify failed: [shady looking signature for /CN=not_my_server]") end it "should provide a helpful error message when hostname was not match with server certificate", :unless => Puppet.features.microsoft_windows? do - Puppet[:confdir] = tmpdir('conf') - cert = Puppet::SSL::CertificateAuthority.new.generate('not_my_server', :dns_alt_names => 'foo,bar,baz').content - - connection = Net::HTTP.new('my_server', 8140) - @searcher.stubs(:network).returns(connection) - ssl_context = OpenSSL::SSL::SSLContext.new - ssl_context.stubs(:current_cert).returns(cert) - connection.stubs(:get).with do - connection.verify_callback.call(true, ssl_context) - end.raises(OpenSSL::SSL::SSLError.new('hostname was not match with server certificate')) - - msg = /Server hostname 'my_server' did not match server certificate; expected one of (.+)/ - expect { @searcher.http_request(:get, stub('request')) }.to( - raise_error(Puppet::Error, msg) do |error| - error.message =~ msg + @searcher.stubs(:network). + returns(a_connection_that_verifies(:has_passed_pre_checks => true, + :in_context => a_store_context(:for_server => 'not_my_server', + :for_aliases => 'foo,bar,baz'), + :fails_with => 'hostname was not match with server certificate')) + + expect { @searcher.http_request(:get, stub('request')) }. + to raise_error(Puppet::Error) do |error| + error.message =~ /Server hostname 'my_server' did not match server certificate; expected one of (.+)/ $1.split(', ').should =~ %w[DNS:foo DNS:bar DNS:baz DNS:not_my_server not_my_server] end - ) end it "should pass along the error message otherwise" do diff --git a/spec/unit/indirector_spec.rb b/spec/unit/indirector_spec.rb index 0c09831db..6349cb777 100755 --- a/spec/unit/indirector_spec.rb +++ b/spec/unit/indirector_spec.rb @@ -37,7 +37,7 @@ describe Puppet::Indirector, "when configuring routes" do } } - expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/fake_indirection does not exist/) + expect { Puppet::Indirector.configure_routes(routes) }.to raise_error(/fake_indirection does not exist/) end it "should fail when given an invalid terminus" do @@ -48,7 +48,7 @@ describe Puppet::Indirector, "when configuring routes" do } } - expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/Could not find terminus fake_terminus/) + expect { Puppet::Indirector.configure_routes(routes) }.to raise_error(/Could not find terminus fake_terminus/) end it "should fail when given an invalid cache" do @@ -59,7 +59,7 @@ describe Puppet::Indirector, "when configuring routes" do } } - expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/Could not find terminus fake_cache/) + expect { Puppet::Indirector.configure_routes(routes) }.to raise_error(/Could not find terminus fake_cache/) end end @@ -87,7 +87,7 @@ describe Puppet::Indirector, "when registering an indirection" do end it "should require a name when registering a model" do - Proc.new {@thingie.send(:indirects) }.should raise_error(ArgumentError) + expect {@thingie.send(:indirects) }.to raise_error(ArgumentError) end it "should create an indirection instance to manage each indirecting model" do @@ -98,7 +98,7 @@ describe Puppet::Indirector, "when registering an indirection" do it "should not allow a model to register under multiple names" do # Keep track of the indirection instance so we can delete it on cleanup @indirection = @thingie.indirects :first - Proc.new { @thingie.indirects :second }.should raise_error(ArgumentError) + expect { @thingie.indirects :second }.to raise_error(ArgumentError) end it "should make the indirection available via an accessor" do diff --git a/spec/unit/interface/action_builder_spec.rb b/spec/unit/interface/action_builder_spec.rb index f779a5461..437a03e88 100755 --- a/spec/unit/interface/action_builder_spec.rb +++ b/spec/unit/interface/action_builder_spec.rb @@ -23,8 +23,9 @@ describe Puppet::Interface::ActionBuilder do end it "should require a block" do - expect { Puppet::Interface::ActionBuilder.build(nil, :foo) }. - should raise_error("Action :foo must specify a block") + expect { + Puppet::Interface::ActionBuilder.build(nil, :foo) + }.to raise_error("Action :foo must specify a block") end it "should require an invocation block" do diff --git a/spec/unit/interface/action_manager_spec.rb b/spec/unit/interface/action_manager_spec.rb index 3a84e4f83..5df891f74 100755 --- a/spec/unit/interface/action_manager_spec.rb +++ b/spec/unit/interface/action_manager_spec.rb @@ -259,7 +259,7 @@ describe Puppet::Interface::ActionManager do when_invoked do |options| true end default } - }.should raise_error /cannot both be default/ + }.to raise_error /cannot both be default/ end end diff --git a/spec/unit/interface/action_spec.rb b/spec/unit/interface/action_spec.rb index 6b68eb149..0d8c62195 100755 --- a/spec/unit/interface/action_spec.rb +++ b/spec/unit/interface/action_spec.rb @@ -6,8 +6,9 @@ describe Puppet::Interface::Action do describe "when validating the action name" do [nil, '', 'foo bar', '-foobar'].each do |input| it "should treat #{input.inspect} as an invalid name" do - expect { Puppet::Interface::Action.new(nil, input) }. - should raise_error(/is an invalid action name/) + expect { + Puppet::Interface::Action.new(nil, input) + }.to raise_error(/is an invalid action name/) end end end @@ -261,7 +262,7 @@ describe Puppet::Interface::Action do option "--foo" action :bar do option "--foo" end end - }.should raise_error ArgumentError, /Option foo conflicts with existing option foo/i + }.to raise_error ArgumentError, /Option foo conflicts with existing option foo/i end it "should fail when a required action option is not provided" do diff --git a/spec/unit/interface/face_collection_spec.rb b/spec/unit/interface/face_collection_spec.rb index 514a624b1..ca31f4096 100755 --- a/spec/unit/interface/face_collection_spec.rb +++ b/spec/unit/interface/face_collection_spec.rb @@ -166,7 +166,7 @@ describe Puppet::Interface::FaceCollection do faulty.each do |input| it "should fail when presented with #{input.inspect} (#{input.class})" do expect { subject.underscorize(input) }. - should raise_error ArgumentError, /not a valid face name/ + to raise_error ArgumentError, /not a valid face name/ end end end diff --git a/spec/unit/interface/option_spec.rb b/spec/unit/interface/option_spec.rb index e73561fba..8afef52e6 100755 --- a/spec/unit/interface/option_spec.rb +++ b/spec/unit/interface/option_spec.rb @@ -17,27 +17,31 @@ describe Puppet::Interface::Option do [:foo, 12, nil, {}, []].each do |input| it "should fail sensible when given #{input.inspect}" do - expect { Puppet::Interface::Option.new(face, input) }. - should raise_error ArgumentError, /is not valid for an option argument/ + expect { + Puppet::Interface::Option.new(face, input) + }.to raise_error ArgumentError, /is not valid for an option argument/ end end ["-foo", "-foo=BAR", "-foo BAR"].each do |input| it "should fail with a single dash for long option #{input.inspect}" do - expect { Puppet::Interface::Option.new(face, input) }. - should raise_error ArgumentError, /long options need two dashes \(--\)/ + expect { + Puppet::Interface::Option.new(face, input) + }.to raise_error ArgumentError, /long options need two dashes \(--\)/ end end end it "requires a face when created" do - expect { Puppet::Interface::Option.new }. - should raise_error ArgumentError, /wrong number of arguments/ + expect { + Puppet::Interface::Option.new + }.to raise_error ArgumentError, /wrong number of arguments/ end it "also requires some declaration arguments when created" do - expect { Puppet::Interface::Option.new(face) }. - should raise_error ArgumentError, /No option declarations found/ + expect { + Puppet::Interface::Option.new(face) + }.to raise_error ArgumentError, /No option declarations found/ end it "should infer the name from an optparse string" do @@ -113,7 +117,7 @@ describe Puppet::Interface::Option do its :default do should be_nil end it "should set a proc as default" do - expect { subject.default = proc { 12 } }.should_not raise_error + expect { subject.default = proc { 12 } }.to_not raise_error end [1, {}, [], Object.new, "foo"].each do |input| diff --git a/spec/unit/interface_spec.rb b/spec/unit/interface_spec.rb index 4ff71ac3d..1b4f70ec3 100755 --- a/spec/unit/interface_spec.rb +++ b/spec/unit/interface_spec.rb @@ -20,15 +20,15 @@ describe Puppet::Interface do describe "#[]" do it "should fail when no version is requested" do - expect { subject[:huzzah] }.should raise_error ArgumentError + expect { subject[:huzzah] }.to raise_error ArgumentError end it "should raise an exception when the requested version is unavailable" do - expect { subject[:huzzah, '17.0.0'] }.should raise_error, Puppet::Error + expect { subject[:huzzah, '17.0.0'] }.to raise_error, Puppet::Error end it "should raise an exception when the requested face doesn't exist" do - expect { subject[:burrble_toot, :current] }.should raise_error, Puppet::Error + expect { subject[:burrble_toot, :current] }.to raise_error, Puppet::Error end describe "version matching" do @@ -98,7 +98,7 @@ describe Puppet::Interface do it "should require a valid version number" do expect { subject.new(:bad_version, 'Rasins') }. - should raise_error ArgumentError + to raise_error ArgumentError end it "should instance-eval any provided block", :'fails_on_ruby_1.9.2' => true do @@ -159,7 +159,7 @@ describe Puppet::Interface do end option "--foo" end - }.should raise_error ArgumentError, /Option foo conflicts with existing option foo on/i + }.to raise_error ArgumentError, /Option foo conflicts with existing option foo on/i end it "should work when two actions have the same option" do diff --git a/spec/unit/module_tool/applications/unpacker_spec.rb b/spec/unit/module_tool/applications/unpacker_spec.rb new file mode 100644 index 000000000..7db0b7d0a --- /dev/null +++ b/spec/unit/module_tool/applications/unpacker_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' +require 'puppet/module_tool/applications' +require 'puppet_spec/modules' + +describe Puppet::ModuleTool::Applications::Unpacker, :fails_on_windows => true do + include PuppetSpec::Files + + let(:target) { tmpdir("unpacker") } + + context "initialization" do + it "should support filename and basic options" do + Puppet::ModuleTool::Applications::Unpacker.new("myusername-mytarball-1.0.0.tar.gz", :target_dir => target) + end + + it "should raise ArgumentError when filename is invalid" do + expect { Puppet::ModuleTool::Applications::Unpacker.new("invalid.tar.gz", :target_dir => target) }.to raise_error(ArgumentError) + end + end + + context "#run" do + let(:cache_base_path) { Pathname.new(tmpdir("unpacker")) } + let(:filename) { tmpdir("module") + "/myusername-mytarball-1.0.0.tar.gz" } + let(:build_dir) { Pathname.new(tmpdir("build_dir")) } + let(:unpacker) do + Puppet::ModuleTool::Applications::Unpacker.new(filename, :target_dir => target) + end + + before :each do + # Mock redhat for most test cases + Facter.stubs(:value).with("operatingsystem").returns("Redhat") + build_dir.stubs(:mkpath => nil, :rmtree => nil, :children => []) + unpacker.stubs(:build_dir).at_least_once.returns(build_dir) + FileUtils.stubs(:mv) + end + + context "on linux" do + it "should attempt to untar file to temporary location using system tar" do + Puppet::Util.expects(:execute).with("tar xzf #{filename} -C #{build_dir}").returns(true) + unpacker.run + end + end + + context "on solaris" do + before :each do + Facter.expects(:value).with("operatingsystem").returns("Solaris") + end + + it "should attempt to untar file to temporary location using gnu tar" do + Puppet::Util.stubs(:which).with('gtar').returns('/usr/sfw/bin/gtar') + Puppet::Util.expects(:execute).with("gtar xzf #{filename} -C #{build_dir}").returns(true) + unpacker.run + end + + it "should throw exception if gtar is not in the path exists" do + Puppet::Util.stubs(:which).with('gtar').returns(nil) + expect { unpacker.run }.to raise_error RuntimeError, "Cannot find the command 'gtar'. Make sure GNU tar is installed, and is in your PATH." + end + end + end + +end diff --git a/spec/unit/network/handler/fileserver_spec.rb b/spec/unit/network/handler/fileserver_spec.rb index 2b8094b8b..9c0683136 100755 --- a/spec/unit/network/handler/fileserver_spec.rb +++ b/spec/unit/network/handler/fileserver_spec.rb @@ -50,9 +50,9 @@ describe Puppet::Network::Handler::FileServer do config_file = tmpfile('fileserver.conf') File.open(config_file, 'w') { |f| f.puts "#{arg} 127.0.0.1/24" } - expect { - Puppet::Network::Handler::FileServer.new(:Config => config_file) - }.should raise_error(Puppet::Network::Handler::FileServerError, "No mount specified for argument #{arg} 127.0.0.1/24") + expect { + Puppet::Network::Handler::FileServer.new(:Config => config_file) + }.to raise_error(Puppet::Network::Handler::FileServerError, "No mount specified for argument #{arg} 127.0.0.1/24") end end end diff --git a/spec/unit/other/transbucket_spec.rb b/spec/unit/other/transbucket_spec.rb index b95a4abca..6eae765cc 100755 --- a/spec/unit/other/transbucket_spec.rb +++ b/spec/unit/other/transbucket_spec.rb @@ -12,7 +12,7 @@ describe Puppet::TransBucket do resource = nil proc { resource = @bucket.to_ral }.should_not raise_error - resource.should be_instance_of(Puppet::Type::Component) + resource.must be_instance_of(Puppet::Type::Component) resource.title.should == "Foo[luke]" end @@ -93,7 +93,7 @@ describe Puppet::TransBucket, " when generating a catalog" do it "should convert all transportable objects to RAL resources" do @catalog = @top.to_catalog @users.each do |name| - @catalog.vertices.find { |r| r.class.name == :notify and r.title == name }.should be_instance_of(Puppet::Type.type(:notify)) + @catalog.vertices.find { |r| r.class.name == :notify and r.title == name }.must be_instance_of(Puppet::Type.type(:notify)) end end @@ -105,18 +105,15 @@ describe Puppet::TransBucket, " when generating a catalog" do it "should convert all transportable buckets to RAL components" do @catalog = @top.to_catalog @fakes.each do |name| - @catalog.vertices.find { |r| r.class.name == :component and r.title == name }.should be_instance_of(Puppet::Type.type(:component)) + @catalog.vertices.find { |r| r.class.name == :component and r.title == name }.must be_instance_of(Puppet::Type.type(:component)) end end it "should add all resources to the graph's resource table" do @catalog = @top.to_catalog - @catalog.resource("fake[top]").should equal(@top) - end - - it "should finalize all resources" do - @catalog = @top.to_catalog - @catalog.vertices.each do |vertex| vertex.should be_finalized end + @fakes.each do |name| + @catalog.resource(name).must be + end end it "should only call to_ral on each resource once" do diff --git a/spec/unit/parser/ast/resource_spec.rb b/spec/unit/parser/ast/resource_spec.rb index 68ad9c229..609bc73f9 100755 --- a/spec/unit/parser/ast/resource_spec.rb +++ b/spec/unit/parser/ast/resource_spec.rb @@ -41,6 +41,33 @@ describe Puppet::Parser::AST::Resource do result.should be_include("two") end + + [5, 5.0, true, false, :three, "foo"].each do |title| + it "should stringify the title if it is a #{title.class}" do + @instance.title.stubs(:safeevaluate).returns title + + result = @resource.evaluate(@scope).map(&:title) + result.first.should == title.to_s + end + end + + [ + {:a => 1}, + /noway/i, + Puppet::Resource.new(:notify, "something"), + Pathname.new("foo"), + (1..50), + nil, + ].each do |title| + it "should fail if the title is a #{title.class}" do + @instance.title.stubs(:safeevaluate).returns title + + expect do + @resource.evaluate(@scope) + end.to raise_error(Puppet::ParseError, /Resource title must be a String, not #{title.class}/) + end + end + it "should create and return one resource objects per title" do titles = [] %w{one two}.each do |title| diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb index 65a304837..4a54fb4f5 100755 --- a/spec/unit/parser/functions/create_resources_spec.rb +++ b/spec/unit/parser/functions/create_resources_spec.rb @@ -19,8 +19,8 @@ describe 'function for dynamically creating resources' do end it 'should require two or three arguments' do - expect { @scope.function_create_resources(['foo']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2 or 3)') - expect { @scope.function_create_resources(['foo', 'bar', 'blah', 'baz']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (4; must be 2 or 3)') + expect { @scope.function_create_resources(['foo']) }.to raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2 or 3)') + expect { @scope.function_create_resources(['foo', 'bar', 'blah', 'baz']) }.to raise_error(ArgumentError, 'create_resources(): wrong number of arguments (4; must be 2 or 3)') end describe 'when the caller does not supply a name parameter' do @@ -57,7 +57,7 @@ describe 'function for dynamically creating resources' do end it 'should fail to add non-existing type' do - expect { @scope.function_create_resources(['create-resource-foo', {}]) }.should raise_error(ArgumentError, 'could not create resource of unknown type create-resource-foo') + expect { @scope.function_create_resources(['create-resource-foo', {}]) }.to raise_error(ArgumentError, 'could not create resource of unknown type create-resource-foo') end it 'should be able to add edges' do @@ -65,8 +65,8 @@ describe 'function for dynamically creating resources' do rg = catalog.to_ral.relationship_graph test = rg.vertices.find { |v| v.title == 'test' } foo = rg.vertices.find { |v| v.title == 'foo' } - test.should be - foo.should be + test.must be + foo.must be rg.path_between(test,foo).should be end @@ -89,7 +89,7 @@ describe 'function for dynamically creating resources' do end it 'should fail if defines are missing params' do - expect { + expect { compile_to_catalog(<<-MANIFEST) define foocreateresource($one) { notify { $name: message => $one } @@ -97,7 +97,7 @@ describe 'function for dynamically creating resources' do create_resources('foocreateresource', {'blah'=>{}}) MANIFEST - }.should raise_error(Puppet::Error, 'Must pass one to Foocreateresource[blah] at line 1 on node foonode') + }.to raise_error(Puppet::Error, 'Must pass one to Foocreateresource[blah] at line 1 on node foonode') end it 'should be able to add multiple defines' do @@ -127,8 +127,8 @@ describe 'function for dynamically creating resources' do rg = catalog.to_ral.relationship_graph test = rg.vertices.find { |v| v.title == 'test' } blah = rg.vertices.find { |v| v.title == 'blah' } - test.should be - blah.should be + test.must be + blah.must be rg.path_between(test,blah).should be catalog.resource(:notify, "blah")['message'].should == 'two' end @@ -165,7 +165,7 @@ describe 'function for dynamically creating resources' do compile_to_catalog(<<-MANIFEST) create_resources('class', {'blah'=>{'one'=>'two'}}) MANIFEST - }.should raise_error(Puppet::Error ,'could not find hostclass blah at line 1 on node foonode') + }.to raise_error(Puppet::Error ,'could not find hostclass blah at line 1 on node foonode') end it 'should be able to add edges' do @@ -182,8 +182,8 @@ describe 'function for dynamically creating resources' do rg = catalog.to_ral.relationship_graph test = rg.vertices.find { |v| v.title == 'test' } tester = rg.vertices.find { |v| v.title == 'tester' } - test.should be - tester.should be + test.must be + tester.must be rg.path_between(tester,test).should be end diff --git a/spec/unit/parser/lexer_spec.rb b/spec/unit/parser/lexer_spec.rb index 3dcae64b2..fbe2cd020 100755 --- a/spec/unit/parser/lexer_spec.rb +++ b/spec/unit/parser/lexer_spec.rb @@ -98,7 +98,7 @@ describe Puppet::Parser::Lexer::TokenList do it "should fail to add tokens sharing a name with an existing token" do @list.add_token :name, "whatever" - lambda { @list.add_token :name, "whatever" }.should raise_error(ArgumentError) + expect { @list.add_token :name, "whatever" }.to raise_error(ArgumentError) end it "should set provided options on tokens being added" do @@ -633,11 +633,11 @@ describe "Puppet::Parser::Lexer in the old tests" do end it "should fail usefully" do - lambda { tokens_scanned_from('^') }.should raise_error(RuntimeError) + expect { tokens_scanned_from('^') }.to raise_error(RuntimeError) end it "should fail if the string is not set" do - lambda { @lexer.fullscan }.should raise_error(Puppet::LexError) + expect { @lexer.fullscan }.to raise_error(Puppet::LexError) end it "should correctly identify keywords" do @@ -662,7 +662,7 @@ describe "Puppet::Parser::Lexer in the old tests" do end it "should correctly parse empty strings" do - lambda { tokens_scanned_from('$var = ""') }.should_not raise_error + expect { tokens_scanned_from('$var = ""') }.to_not raise_error end it "should correctly parse virtual resources" do @@ -724,7 +724,7 @@ describe "Puppet::Parser::Lexer in the old tests when lexing example files" do it "should correctly lex #{file}" do lexer = Puppet::Parser::Lexer.new lexer.file = file - expect { lexer.fullscan }.should_not raise_error + expect { lexer.fullscan }.to_not raise_error end end end diff --git a/spec/unit/provider/augeas/augeas_spec.rb b/spec/unit/provider/augeas/augeas_spec.rb index 9385c0cd7..03073411e 100755 --- a/spec/unit/provider/augeas/augeas_spec.rb +++ b/spec/unit/provider/augeas/augeas_spec.rb @@ -606,4 +606,82 @@ describe provider_class do File.read(target).should =~ /PermitRootLogin no/ end end + + # Run initialisation tests of the real Augeas library to test our open_augeas + # method. This relies on Augeas and ruby-augeas on the host to be + # functioning. + describe "augeas lib initialisation", :if => Puppet.features.augeas? do + # Expect lenses for fstab and hosts + it "should have loaded standard files by default" do + aug = @provider.open_augeas + aug.should_not == nil + aug.match("/files/etc/fstab").should == ["/files/etc/fstab"] + aug.match("/files/etc/hosts").should == ["/files/etc/hosts"] + aug.match("/files/etc/test").should == [] + end + + # Only the file specified should be loaded + it "should load one file if incl/lens used" do + @resource[:incl] = "/etc/hosts" + @resource[:lens] = "Hosts.lns" + + aug = @provider.open_augeas + aug.should_not == nil + aug.match("/files/etc/fstab").should == [] + aug.match("/files/etc/hosts").should == ["/files/etc/hosts"] + aug.match("/files/etc/test").should == [] + end + + it "should also load lenses from load_path" do + @resource[:load_path] = my_fixture_dir + + aug = @provider.open_augeas + aug.should_not == nil + aug.match("/files/etc/fstab").should == ["/files/etc/fstab"] + aug.match("/files/etc/hosts").should == ["/files/etc/hosts"] + aug.match("/files/etc/test").should == ["/files/etc/test"] + end + + it "should also load lenses from pluginsync'd path" do + Puppet[:libdir] = my_fixture_dir + + aug = @provider.open_augeas + aug.should_not == nil + aug.match("/files/etc/fstab").should == ["/files/etc/fstab"] + aug.match("/files/etc/hosts").should == ["/files/etc/hosts"] + aug.match("/files/etc/test").should == ["/files/etc/test"] + end + end + + describe "get_load_path" do + it "should offer no load_path by default" do + @provider.get_load_path(@resource).should == "" + end + + it "should offer one path from load_path" do + @resource[:load_path] = "/foo" + @provider.get_load_path(@resource).should == "/foo" + end + + it "should offer multiple colon-separated paths from load_path" do + @resource[:load_path] = "/foo:/bar:/baz" + @provider.get_load_path(@resource).should == "/foo:/bar:/baz" + end + + it "should offer multiple paths in array from load_path" do + @resource[:load_path] = ["/foo", "/bar", "/baz"] + @provider.get_load_path(@resource).should == "/foo:/bar:/baz" + end + + it "should offer pluginsync augeas/lenses subdir" do + Puppet[:libdir] = my_fixture_dir + @provider.get_load_path(@resource).should == "#{my_fixture_dir}/augeas/lenses" + end + + it "should offer both pluginsync and load_path paths" do + Puppet[:libdir] = my_fixture_dir + @resource[:load_path] = ["/foo", "/bar", "/baz"] + @provider.get_load_path(@resource).should == "/foo:/bar:/baz:#{my_fixture_dir}/augeas/lenses" + end + end end diff --git a/spec/unit/provider/nameservice/directoryservice_spec.rb b/spec/unit/provider/nameservice/directoryservice_spec.rb index c11388a04..f5f3f4d88 100755 --- a/spec/unit/provider/nameservice/directoryservice_spec.rb +++ b/spec/unit/provider/nameservice/directoryservice_spec.rb @@ -31,7 +31,7 @@ require 'spec_helper' with([:dseditgroup, '-o', 'edit', '-n', '.', '-a', add, group]) end - expect { @provider.set(:members, desired) }.should_not raise_error + expect { @provider.set(:members, desired) }.to_not raise_error end end end @@ -40,9 +40,9 @@ describe 'DirectoryService.single_report' do it 'should fail on OS X < 10.4' do Puppet::Provider::NameService::DirectoryService.stubs(:get_macosx_version_major).returns("10.3") - lambda { + expect { Puppet::Provider::NameService::DirectoryService.single_report('resource_name') - }.should raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4") + }.to raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4") end it 'should use url data on 10.4' do @@ -76,9 +76,9 @@ describe 'DirectoryService.get_exec_preamble' do it 'should fail on OS X < 10.4' do Puppet::Provider::NameService::DirectoryService.stubs(:get_macosx_version_major).returns("10.3") - lambda { + expect { Puppet::Provider::NameService::DirectoryService.get_exec_preamble('-list') - }.should raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4") + }.to raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4") end it 'should use url data on 10.4' do @@ -140,7 +140,7 @@ describe 'DirectoryService password behavior' do it 'should fail if a salted-SHA512 password hash is not passed in >= 10.7' do expect { subject.set_password('jeff', 'uid', 'badpassword') - }.should raise_error(RuntimeError, /OS X 10.7 requires a Salted SHA512 hash password of 136 characters./) + }.to raise_error(RuntimeError, /OS X 10.7 requires a Salted SHA512 hash password of 136 characters./) end it 'should convert xml-to-binary and binary-to-xml when setting the pw on >= 10.7' do diff --git a/spec/unit/provider/package/freebsd_spec.rb b/spec/unit/provider/package/freebsd_spec.rb index 9c8038791..4fa9aa281 100755 --- a/spec/unit/provider/package/freebsd_spec.rb +++ b/spec/unit/provider/package/freebsd_spec.rb @@ -36,7 +36,7 @@ describe provider_class do Puppet::Util::Execution.expects(:withenv).once.with({:PKG_PATH => path}).yields @provider.expects(:pkgadd).once.with("mypackage") - expect { @provider.install }.should_not raise_error + expect { @provider.install }.to_not raise_error end %w{http https ftp}.each do |protocol| @@ -47,7 +47,7 @@ describe provider_class do Puppet::Util::Execution.expects(:withenv).once.with({:PACKAGESITE => path}).yields @provider.expects(:pkgadd).once.with('-r', "mypackage") - expect { @provider.install }.should_not raise_error + expect { @provider.install }.to_not raise_error end end end diff --git a/spec/unit/provider/package/msi_spec.rb b/spec/unit/provider/package/msi_spec.rb index d6384cf43..aa39de2ef 100644 --- a/spec/unit/provider/package/msi_spec.rb +++ b/spec/unit/provider/package/msi_spec.rb @@ -1,170 +1,237 @@ require 'spec_helper' -describe 'Puppet::Provider::Package::Msi' do - include PuppetSpec::Files +describe Puppet::Type.type(:package).provider(:msi) do + let (:name) { 'mysql-5.1.58-win-x64' } + let (:source) { 'E:\mysql-5.1.58-win-x64.msi' } + let (:productcode) { '{E437FFB6-5C49-4DAC-ABAE-33FF065FE7CC}' } + let (:packagecode) { '{5A6FD560-763A-4BC1-9E03-B18DFFB7C72C}' } + let (:resource) { Puppet::Type.type(:package).new(:name => name, :provider => :msi, :source => source) } + let (:provider) { resource.provider } + let (:execute_options) do {:combine => true} end + + def installer(productcodes) + installer = mock + installer.expects(:UILevel=).with(2) + + installer.stubs(:ProductState).returns(5) + installer.stubs(:Products).returns(productcodes) + productcodes.each do |guid| + installer.stubs(:ProductInfo).with(guid, 'ProductName').returns("name-#{guid}") + installer.stubs(:ProductInfo).with(guid, 'PackageCode').returns("package-#{guid}") + end + + MsiPackage.stubs(:installer).returns(installer) + end before :each do - Puppet::Type.type(:package).stubs(:defaultprovider).returns(Puppet::Type.type(:package).provider(:msi)) - Puppet[:vardir] = tmpdir('msi') - @state_dir = File.join(Puppet[:vardir], 'db', 'package', 'msi') + # make sure we never try to execute msiexec + provider.expects(:execute).never + end + + describe 'provider features' do + it { should be_installable } + it { should be_uninstallable } + it { should be_install_options } end - describe 'when installing' do - it 'should create a state file' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) - resource.provider.stubs(:execute) - resource.provider.install + context '::instances' do + it 'should return an array of provider instances' do + installer([1, 2]) - File.should be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml') + MsiPackage.map do |pkg| + pkg[:name].should == "name-#{pkg[:productcode]}" + pkg[:ensure].should == :installed + pkg[:provider].should == :msi + pkg[:packagecode].should == "package-#{pkg[:productcode]}" + end.count.should == 2 end - it 'should use the install_options as parameter/value pairs' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi', - :install_options => { 'INSTALLDIR' => 'C:\mysql-here' } - ) + it 'should return an empty array of none found' do + installer([]) - resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR=C:\mysql-here') - resource.provider.install + MsiPackage.to_a.size.should == 0 end + end - it 'should only quote the value when an install_options value has a space in it' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi', - :install_options => { 'INSTALLDIR' => 'C:\mysql here' } - ) + context '#query' do + let (:package) do { + :name => name, + :ensure => :installed, + :provider => :msi, + :productcode => productcode, + :packagecode => packagecode.upcase + } + end - resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR="C:\mysql here"') - resource.provider.install + before :each do + MsiPackage.stubs(:each).yields(package) end - it 'should escape embedded quotes in install_options values with spaces' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi', - :install_options => { 'INSTALLDIR' => 'C:\mysql "here"' } - ) + it 'should match package codes case-insensitively' do + resource[:name] = packagecode.downcase + + provider.query.should == package + end - resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR="C:\mysql \"here\""') - resource.provider.install + it 'should match product name' do + resource[:name] = name + + provider.query.should == package end - it 'should not create a state file, if the installation fails' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) - resource.provider.stubs(:execute).raises(Puppet::ExecutionFailure.new("Execution of 'msiexec.exe' returned 128: Blargle")) - expect { resource.provider.install }.to raise_error(Puppet::ExecutionFailure, /msiexec\.exe/) + it 'should return nil if none found' do + resource[:name] = 'not going to find it' - File.should_not be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml') + provider.query.should be_nil end + end + + context '#install' do + before :each do + provider.stubs(:execute) + end + + it 'should require the source parameter' do + resource = Puppet::Type.type(:package).new(:name => name, :provider => :msi) - it 'should fail if the source parameter is not set' do expect do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64' - ).provider.install + resource.provider.install end.to raise_error(Puppet::Error, /The source parameter is required when using the MSI provider/) end - it 'should fail if the source parameter is empty' do + it 'should install using the source and install_options' do + resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql-5.1' } + + provider.expects(:execute).with("msiexec.exe /qn /norestart /i #{source} INSTALLDIR=C:\\mysql-5.1", execute_options) + provider.expects(:exit_status).returns(0) + + provider.install + end + + it 'should warn if the package requests a reboot' do + provider.stubs(:exit_status).returns(194) + + provider.expects(:warning).with('The package requested a reboot to finish the operation.') + + provider.install + end + + it 'should warn if reboot initiated' do + provider.stubs(:exit_status).returns(1641) + + provider.expects(:warning).with('The package installed successfully and the system is rebooting now.') + + provider.install + end + + it 'should warn if reboot required' do + provider.stubs(:exit_status).returns(3010) + + provider.expects(:warning).with('The package installed successfully, but the system must be rebooted.') + + provider.install + end + + it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do + provider.stubs(:execute) + provider.stubs(:exit_status).returns(5) + expect do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => '' - ) - end.to raise_error(Puppet::Error, /The source parameter cannot be empty when using the MSI provider/) + provider.install + end.to raise_error(Puppet::Util::Windows::Error, /Access is denied/) end end - describe 'when uninstalling' do + context '#uninstall' do before :each do - FileUtils.mkdir_p(@state_dir) - File.open(File.join(@state_dir, 'mysql-5.1.58-winx64.yml'), 'w') {|f| f.puts 'Hello'} + resource[:ensure] = :absent + provider.set(:productcode => productcode) + end + + it 'should require the productcode' do + provider.set(:productcode => nil) + expect do + provider.uninstall + end.to raise_error(Puppet::Error, /The productcode property is missing./) end - it 'should remove the state file' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) - resource.provider.stubs(:msiexec) - resource.provider.uninstall + it 'should uninstall using the productcode' do + provider.expects(:execute).with("msiexec.exe /qn /norestart /x #{productcode}", execute_options) + provider.expects(:exit_status).returns(0) + + provider.uninstall + end + + it 'should warn if the package requests a reboot' do + provider.stubs(:execute) + provider.stubs(:exit_status).returns(194) + + provider.expects(:warning).with('The package requested a reboot to finish the operation.') + + provider.uninstall + end + + it 'should warn if reboot initiated' do + provider.stubs(:execute) + provider.stubs(:exit_status).returns(1641) + + provider.expects(:warning).with('The package uninstalled successfully and the system is rebooting now.') - File.should_not be_exists File.join(Puppet[:vardir], 'db', 'package', 'msi', 'mysql-5.1.58-winx64.yml') + provider.uninstall end - it 'should leave the state file if uninstalling fails' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) - resource.provider.stubs(:msiexec).raises(Puppet::ExecutionFailure.new("Execution of 'msiexec.exe' returned 128: Blargle")) - expect { resource.provider.uninstall }.to raise_error(Puppet::ExecutionFailure, /msiexec\.exe/) + it 'should warn if reboot required' do + provider.stubs(:execute) + provider.stubs(:exit_status).returns(3010) - File.should be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml') + provider.expects(:warning).with('The package uninstalled successfully, but the system must be rebooted.') + + provider.uninstall end - it 'should fail if the source parameter is not set' do + it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do + provider.stubs(:execute) + provider.stubs(:exit_status).returns(5) + expect do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64' - ).provider.install - end.to raise_error(Puppet::Error, /The source parameter is required when using the MSI provider/) + provider.uninstall + end.to raise_error(Puppet::Util::Windows::Error, /Failed to uninstall.*Access is denied/) end + end + context '#validate_source' do it 'should fail if the source parameter is empty' do expect do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => '' - ) + resource[:source] = '' end.to raise_error(Puppet::Error, /The source parameter cannot be empty when using the MSI provider/) end - end - describe 'when enumerating instances' do - it 'should consider the base of the state file name to be the name of the package' do - FileUtils.mkdir_p(@state_dir) - package_names = ['GoogleChromeStandaloneEnterprise', 'mysql-5.1.58-winx64', 'postgresql-8.3'] + it 'should accept a source' do + resource[:source] = source + end + end - package_names.each do |state_file| - File.open(File.join(@state_dir, "#{state_file}.yml"), 'w') {|f| f.puts 'Hello'} - end + context '#install_options' do + it 'should return nil by default' do + provider.install_options.should be_nil + end - installed_package_names = Puppet::Type.type(:package).provider(:msi).instances.collect {|p| p.name} + it 'should use the install_options as parameter/value pairs' do + resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql-here' } - installed_package_names.should =~ package_names + provider.install_options.should == ['INSTALLDIR=C:\mysql-here'] end - end - it 'should consider the package installed if the state file is present' do - FileUtils.mkdir_p(@state_dir) - File.open(File.join(@state_dir, 'mysql-5.1.58-winx64.yml'), 'w') {|f| f.puts 'Hello'} - - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) + it 'should only quote the value when an install_options value has a space in it' do + resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql here' } - resource.provider.query.should == { - :name => 'mysql-5.1.58-winx64', - :ensure => :installed - } - end + provider.install_options.should == ['INSTALLDIR="C:\mysql here"'] + end - it 'should consider the package absent if the state file is missing' do - resource = Puppet::Type.type(:package).new( - :name => 'mysql-5.1.58-winx64', - :source => 'E:\mysql-5.1.58-winx64.msi' - ) + it 'should escape embedded quotes in install_options values with spaces' do + resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql "here"' } - resource.provider.query.should be_nil + provider.install_options.should == ['INSTALLDIR="C:\mysql \"here\""'] + end end end diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 1289c6ea1..d9b7a7533 100755 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -71,6 +71,7 @@ describe provider_class do name == provider.resource[:name] end + provider.expects(:execpipe).with(%w{/bin/pkg_info -I bash}).yields('') provider.install ENV.should_not be_key 'PKG_PATH' diff --git a/spec/unit/provider/package/pkgdmg_spec.rb b/spec/unit/provider/package/pkgdmg_spec.rb index f8b23167a..3a4f13e0f 100755 --- a/spec/unit/provider/package/pkgdmg_spec.rb +++ b/spec/unit/provider/package/pkgdmg_spec.rb @@ -14,12 +14,12 @@ describe Puppet::Type.type(:package).provider(:pkgdmg) do end it "no source is specified" do - expect { provider.install }.should raise_error(Puppet::Error, /must specify a package source/) + expect { provider.install }.to raise_error(Puppet::Error, /must specify a package source/) end it "the source does not end in .dmg or .pkg" do resource[:source] = "bar" - expect { provider.install }.should raise_error(Puppet::Error, /must specify a source string ending in .*dmg.*pkg/) + expect { provider.install }.to raise_error(Puppet::Error, /must specify a source string ending in .*dmg.*pkg/) end end @@ -40,7 +40,7 @@ describe Puppet::Type.type(:package).provider(:pkgdmg) do it "should fail when a disk image with no system entities is mounted" do described_class.stubs(:hdiutil).returns(empty_hdiutil_plist) - expect { provider.install }.should raise_error(Puppet::Error, /No disk entities/) + expect { provider.install }.to raise_error(Puppet::Error, /No disk entities/) end it "should call hdiutil to mount and eject the disk image" do diff --git a/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb b/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb index 1bf8b7eb3..069a92a32 100644 --- a/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +++ b/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb @@ -1539,7 +1539,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if end it 'should set the arguments' do - resource.provider.expects(:arguments=).with([@arguments]) + resource.provider.expects(:arguments=).with(@arguments) resource.provider.create end diff --git a/spec/unit/provider/service/openrc_spec.rb b/spec/unit/provider/service/openrc_spec.rb new file mode 100755 index 000000000..7dc30deb8 --- /dev/null +++ b/spec/unit/provider/service/openrc_spec.rb @@ -0,0 +1,209 @@ +#!/usr/bin/env rspec + +require 'spec_helper' + +describe Puppet::Type.type(:service).provider(:openrc) do + + before :each do + Puppet::Type.type(:service).stubs(:defaultprovider).returns described_class + ['/sbin/rc-service', '/bin/rc-status', '/sbin/rc-update'].each do |command| + described_class.stubs(:which).with(command).returns(command) + end + end + + describe ".instances" do + + it "should have an instances method" do + described_class.should respond_to :instances + end + + it "should get a list of services from rc-service --list" do + described_class.expects(:rcservice).with('-C','--list').returns File.read(my_fixture('rcservice_list')) + described_class.instances.map(&:name).should == [ + 'alsasound', + 'consolefont', + 'lvm-monitoring', + 'pydoc-2.7', + 'pydoc-3.2', + 'wpa_supplicant', + 'xdm', + 'xdm-setup' + ] + end + end + + describe "#start" do + it "should use the supplied start command if specified" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :start => '/bin/foo')) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.start + end + it "should start the service with rc-service start otherwise" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :squelch => true) + provider.start + end + end + + describe "#stop" do + it "should use the supplied stop command if specified" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :stop => '/bin/foo')) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.stop + end + it "should stop the service with rc-service stop otherwise" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :squelch => true) + provider.stop + end + end + + describe "#enabled?" do + + before :each do + described_class.any_instance.stubs(:rcstatus).with('-C','-a').returns File.read(my_fixture('rcstatus')) + end + + it "should run rc-status to get a list of enabled services" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + provider.expects(:rcstatus).with('-C','-a').returns "\n" + provider.enabled? + end + + ['hwclock', 'modules', 'urandom'].each do |service| + it "should consider service #{service} in runlevel boot as enabled" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => service)) + provider.enabled?.should == :true + end + end + + ['netmount', 'xdm', 'local', 'foo_with_very_very_long_servicename_no_still_not_the_end_wait_for_it_almost_there_almost_there_now_finally_the_end'].each do |service| + it "should consider service #{service} in runlevel default as enabled" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => service)) + provider.enabled?.should == :true + end + end + + ['net.eth0', 'pcscd'].each do |service| + it "should consider service #{service} in dynamic runlevel: hotplugged as disabled" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => service)) + provider.enabled?.should == :false + end + end + + ['sysfs', 'udev-mount'].each do |service| + it "should consider service #{service} in dynamic runlevel: needed as disabled" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => service)) + provider.enabled?.should == :false + end + end + + ['sshd'].each do |service| + it "should consider service #{service} in dynamic runlevel: manual as disabled" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => service)) + provider.enabled?.should == :false + end + end + + end + + describe "#enable" do + it "should run rc-update add to enable a service" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + provider.expects(:rcupdate).with('-C', :add, 'sshd') + provider.enable + end + end + + describe "#disable" do + it "should run rc-update del to disable a service" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + provider.expects(:rcupdate).with('-C', :del, 'sshd') + provider.disable + end + end + + describe "#status" do + + describe "when a special status command if specified" do + it "should use the status command from the resource" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.status + end + + it "should return :stopped when status command returns with a non-zero exitcode" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + $CHILD_STATUS.stubs(:exitstatus).returns 3 + provider.status.should == :stopped + end + + it "should return :running when status command returns with a zero exitcode" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + $CHILD_STATUS.stubs(:exitstatus).returns 0 + provider.status.should == :running + end + end + + describe "when hasstatus is false" do + it "should return running if a pid can be found" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:getpid).returns 1000 + provider.status.should == :running + end + + it "should return stopped if no pid can be found" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:getpid).returns nil + provider.status.should == :stopped + end + end + + describe "when hasstatus is true" do + it "should return running if rc-service status exits with a zero exitcode" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true) + $CHILD_STATUS.stubs(:exitstatus).returns 0 + provider.status.should == :running + end + + it "should return stopped if rc-service status exits with a non-zero exitcode" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true) + $CHILD_STATUS.stubs(:exitstatus).returns 3 + provider.status.should == :stopped + end + end + end + + describe "#restart" do + it "should use the supplied restart command if specified" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :restart => '/bin/foo')) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.restart + end + + it "should restart the service with rc-service restart if hasrestart is true" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => true)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true) + provider.restart + end + + it "should restart the service with rc-service stop/start if hasrestart is false" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => false)) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true).never + provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :squelch => true) + provider.restart + end + end + +end diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index 07e4f4d1a..038c91c4e 100755 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -8,16 +8,19 @@ require 'spec_helper' require 'win32/service' if Puppet.features.microsoft_windows? describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features.microsoft_windows? do + let(:name) { 'nonexistentservice' } + let(:resource) { Puppet::Type.type(:service).new(:name => name, :provider => :windows) } + let(:provider) { resource.provider } + let(:config) { Struct::ServiceConfigInfo.new } + let(:status) { Struct::ServiceStatus.new } before :each do - @resource = Puppet::Type.type(:service).new(:name => 'snmptrap', :provider => :windows) + # make sure we never actually execute anything (there are two execute methods) + provider.class.expects(:execute).never + provider.expects(:execute).never - @config = Struct::ServiceConfigInfo.new - - @status = Struct::ServiceStatus.new - - Win32::Service.stubs(:config_info).with(@resource[:name]).returns(@config) - Win32::Service.stubs(:status).with(@resource[:name]).returns(@status) + Win32::Service.stubs(:config_info).with(name).returns(config) + Win32::Service.stubs(:status).with(name).returns(status) end describe ".instances" do @@ -30,102 +33,98 @@ describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features. end describe "#start" do - it "should call out to the Win32::Service API to start the service" do - @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START) + before :each do + config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START) + end - Win32::Service.expects(:start).with( @resource[:name] ) + it "should start the service" do + provider.expects(:net).with(:start, name) - @resource.provider.start + provider.start end - it "should handle when Win32::Service.start raises a Win32::Service::Error" do - @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START) - - Win32::Service.expects(:start).with( @resource[:name] ).raises( - Win32::Service::Error.new("The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.") - ) + it "should raise an error if the start command fails" do + provider.expects(:net).with(:start, name).raises(Puppet::ExecutionFailure, "The service name is invalid.") - expect { @resource.provider.start }.to raise_error( - Puppet::Error, - /Cannot start .*, error was: The service cannot be started, either/ - ) + expect { + provider.start + }.to raise_error(Puppet::Error, /Cannot start #{name}, error was: The service name is invalid./) end describe "when the service is disabled" do before :each do - @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) - Win32::Service.stubs(:start).with(@resource[:name]) + config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) end it "should refuse to start if not managing enable" do - expect { @resource.provider.start }.to raise_error(Puppet::Error, /Will not start disabled service/) + expect { provider.start }.to raise_error(Puppet::Error, /Will not start disabled service/) end it "should enable if managing enable and enable is true" do - @resource[:enable] = :true + resource[:enable] = :true - Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_AUTO_START).returns(Win32::Service) + provider.expects(:net).with(:start, name) + Win32::Service.expects(:configure).with('service_name' => name, 'start_type' => Win32::Service::SERVICE_AUTO_START).returns(Win32::Service) - @resource.provider.start + provider.start end it "should manual start if managing enable and enable is false" do - @resource[:enable] = :false + resource[:enable] = :false - Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DEMAND_START).returns(Win32::Service) + provider.expects(:net).with(:start, name) + Win32::Service.expects(:configure).with('service_name' => name, 'start_type' => Win32::Service::SERVICE_DEMAND_START).returns(Win32::Service) - @resource.provider.start + provider.start end end end describe "#stop" do - it "should call out to the Win32::Service API to stop the service" do - Win32::Service.expects(:stop).with( @resource[:name] ) - @resource.provider.stop - end + it "should stop a running service" do + provider.expects(:net).with(:stop, name) + + provider.stop + end - it "should handle when Win32::Service.stop raises a Win32::Service::Error" do - Win32::Service.expects(:stop).with( @resource[:name] ).raises( - Win32::Service::Error.new("should not try to stop an already stopped service.") - ) + it "should raise an error if the stop command fails" do + provider.expects(:net).with(:stop, name).raises(Puppet::ExecutionFailure, 'The service name is invalid.') - expect { @resource.provider.stop }.to raise_error( - Puppet::Error, - /Cannot stop .*, error was: should not try to stop an already stopped service/ - ) + expect { + provider.stop + }.to raise_error(Puppet::Error, /Cannot stop #{name}, error was: The service name is invalid./) end end describe "#status" do ['stopped', 'paused', 'stop pending', 'pause pending'].each do |state| it "should report a #{state} service as stopped" do - @status.current_state = state + status.current_state = state - @resource.provider.status.should == :stopped + provider.status.should == :stopped end end ["running", "continue pending", "start pending" ].each do |state| it "should report a #{state} service as running" do - @status.current_state = state + status.current_state = state - @resource.provider.status.should == :running + provider.status.should == :running end end end describe "#enabled?" do it "should report a service with a startup type of manual as manual" do - @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DEMAND_START) + config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DEMAND_START) - @resource.provider.enabled?.should == :manual + provider.enabled?.should == :manual end it "should report a service with a startup type of disabled as false" do - @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) + config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) - @resource.provider.enabled?.should == :false + provider.enabled?.should == :false end # We need to guard this section explicitly since rspec will always @@ -134,9 +133,9 @@ describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features. [Win32::Service::SERVICE_AUTO_START, Win32::Service::SERVICE_BOOT_START, Win32::Service::SERVICE_SYSTEM_START].each do |start_type_const| start_type = Win32::Service.get_start_type(start_type_const) it "should report a service with a startup type of '#{start_type}' as true" do - @config.start_type = start_type + config.start_type = start_type - @resource.provider.enabled?.should == :true + provider.enabled?.should == :true end end end @@ -144,23 +143,22 @@ describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features. describe "#enable" do it "should set service start type to Service_Auto_Start when enabled" do - Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_AUTO_START).returns(Win32::Service) - @resource.provider.enable + Win32::Service.expects(:configure).with('service_name' => name, 'start_type' => Win32::Service::SERVICE_AUTO_START).returns(Win32::Service) + provider.enable end end describe "#disable" do it "should set service start type to Service_Disabled when disabled" do - Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DISABLED).returns(Win32::Service) - @resource.provider.disable + Win32::Service.expects(:configure).with('service_name' => name, 'start_type' => Win32::Service::SERVICE_DISABLED).returns(Win32::Service) + provider.disable end end describe "#manual_start" do it "should set service start type to Service_Demand_Start (manual) when manual" do - Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DEMAND_START).returns(Win32::Service) - @resource.provider.manual_start + Win32::Service.expects(:configure).with('service_name' => name, 'start_type' => Win32::Service::SERVICE_DEMAND_START).returns(Win32::Service) + provider.manual_start end end - end diff --git a/spec/unit/provider/user/useradd_spec.rb b/spec/unit/provider/user/useradd_spec.rb index 724fc12c0..5aabfb745 100755 --- a/spec/unit/provider/user/useradd_spec.rb +++ b/spec/unit/provider/user/useradd_spec.rb @@ -88,6 +88,13 @@ describe provider_class do @resource.stubs(:managehome?).returns true @provider.check_manage_home.must == ["-m"] end + + it "should return an array with -r flag if home is managed" do + @resource.stubs(:managehome?).returns true + @resource.stubs(:ensure) == :absent + @provider.stubs(:command).returns("userdel") + @provider.deletecmd.must == ["userdel", "-r", "fakeval"] + end it "should return an array with -M if home is not managed and on Redhat" do Facter.stubs(:value).with("operatingsystem").returns("RedHat") diff --git a/spec/unit/reports/store_spec.rb b/spec/unit/reports/store_spec.rb index b4f849cde..f149eff5e 100755 --- a/spec/unit/reports/store_spec.rb +++ b/spec/unit/reports/store_spec.rb @@ -45,31 +45,31 @@ describe processor do @report.process end - ['..', 'hello/', '/hello', 'he/llo', 'hello/..', '.'].each do |node| - it "rejects #{node.inspect}" do - @report.host = node - expect { @report.process }.to raise_error(ArgumentError, /Invalid node/) - end + it "rejects invalid hostnames" do + @report.host = ".." + FileTest.expects(:exists?).never + Tempfile.expects(:new).never + expect { @report.process }.to raise_error(ArgumentError, /Invalid node/) end + end - ['.hello', 'hello.', '..hi', 'hi..'].each do |node| - it "accepts #{node.inspect}" do - @report.host = node - @report.process - end + describe "::destroy" do + it "rejects invalid hostnames" do + File.expects(:unlink).never + expect { processor.destroy("..") }.to raise_error(ArgumentError, /Invalid node/) end end - describe "::destroy" do + describe "::validate_host" do ['..', 'hello/', '/hello', 'he/llo', 'hello/..', '.'].each do |node| it "rejects #{node.inspect}" do - expect { processor.destroy(node) }.to raise_error(ArgumentError, /Invalid node/) + expect { processor.validate_host(node) }.to raise_error(ArgumentError, /Invalid node/) end end ['.hello', 'hello.', '..hi', 'hi..'].each do |node| it "accepts #{node.inspect}" do - processor.destroy(node) + processor.validate_host(node) end end end diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb index f7a3e8785..a39f55fce 100755 --- a/spec/unit/resource/catalog_spec.rb +++ b/spec/unit/resource/catalog_spec.rb @@ -309,7 +309,12 @@ describe Puppet::Resource::Catalog, "when compiling" do end it "should add all resources as RAL instances" do - @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::Type) } + @resources.each do |resource| + # Warning: a failure here will result in "global resource iteration is + # deprecated" being raised, because the rspec rendering to get the + # result tries to call `each` on the resource, and that raises. + @catalog.resource(resource.ref).must be_a_kind_of(Puppet::Type) + end end it "should copy the tag list to the new catalog" do @@ -416,8 +421,8 @@ describe Puppet::Resource::Catalog, "when compiling" do it "should provide a method to add one or more resources" do @catalog.add_resource @one, @two - @catalog.resource(@one.ref).should equal(@one) - @catalog.resource(@two.ref).should equal(@two) + @catalog.resource(@one.ref).must equal(@one) + @catalog.resource(@two.ref).must equal(@two) end it "should add resources to the relationship graph if it exists" do @@ -433,20 +438,18 @@ describe Puppet::Resource::Catalog, "when compiling" do it "should make all vertices available by resource reference" do @catalog.add_resource(@one) - @catalog.resource(@one.ref).should equal(@one) - @catalog.vertices.find { |r| r.ref == @one.ref }.should equal(@one) + @catalog.resource(@one.ref).must equal(@one) + @catalog.vertices.find { |r| r.ref == @one.ref }.must equal(@one) end it "should canonize how resources are referred to during retrieval when both type and title are provided" do @catalog.add_resource(@one) - - @catalog.resource("notify", "one").should equal(@one) + @catalog.resource("notify", "one").must equal(@one) end it "should canonize how resources are referred to during retrieval when just the title is provided" do @catalog.add_resource(@one) - - @catalog.resource("notify[one]", nil).should equal(@one) + @catalog.resource("notify[one]", nil).must equal(@one) end it "should not allow two resources with the same resource reference" do @@ -502,26 +505,28 @@ describe Puppet::Resource::Catalog, "when compiling" do it "should be able to find resources by reference" do @catalog.add_resource @one - @catalog.resource(@one.ref).should equal(@one) + @catalog.resource(@one.ref).must equal(@one) end it "should be able to find resources by reference or by type/title tuple" do @catalog.add_resource @one - @catalog.resource("notify", "one").should equal(@one) + @catalog.resource("notify", "one").must equal(@one) end it "should have a mechanism for removing resources" do - @catalog.add_resource @one - @one.expects :remove + @catalog.add_resource(@one) + @catalog.resource(@one.ref).must be + @catalog.vertex?(@one).must be_true + @catalog.remove_resource(@one) - @catalog.resource(@one.ref).should be_nil - @catalog.vertex?(@one).should be_false + @catalog.resource(@one.ref).must be_nil + @catalog.vertex?(@one).must be_false end it "should have a method for creating aliases for resources" do @catalog.add_resource @one @catalog.alias(@one, "other") - @catalog.resource("notify", "other").should equal(@one) + @catalog.resource("notify", "other").must equal(@one) end it "should ignore conflicting aliases that point to the aliased resource" do @@ -534,7 +539,7 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.add_resource(resource) - @catalog.resource(:file, @basepath+"/something").should equal(resource) + @catalog.resource(:file, @basepath+"/something").must equal(resource) end it "should not create aliases for non-isomorphic resources whose names do not match their titles" do @@ -550,7 +555,7 @@ describe Puppet::Resource::Catalog, "when compiling" do it "should alias using the class name from the resource reference, not the resource class name" do @catalog.add_resource @one @catalog.alias(@one, "other") - @catalog.resource("notify", "other").should equal(@one) + @catalog.resource("notify", "other").must equal(@one) end it "should fail to add an alias if the aliased name already exists" do @@ -565,13 +570,13 @@ describe Puppet::Resource::Catalog, "when compiling" do it "should not create aliases that point back to the resource" do @catalog.alias(@one, "one") - @catalog.resource(:notify, "one").should be_nil + @catalog.resource(:notify, "one").must be_nil end it "should be able to look resources up by their aliases" do @catalog.add_resource @one @catalog.alias @one, "two" - @catalog.resource(:notify, "two").should equal(@one) + @catalog.resource(:notify, "two").must equal(@one) end it "should remove resource aliases when the target resource is removed" do @@ -579,14 +584,14 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.alias(@one, "other") @one.expects :remove @catalog.remove_resource(@one) - @catalog.resource("notify", "other").should be_nil + @catalog.resource("notify", "other").must be_nil end it "should add an alias for the namevar when the title and name differ on isomorphic resource types" do resource = Puppet::Type.type(:file).new :path => @basepath+"/something", :title => "other", :content => "blah" resource.expects(:isomorphic?).returns(true) @catalog.add_resource(resource) - @catalog.resource(:file, "other").should equal(resource) + @catalog.resource(:file, "other").must equal(resource) @catalog.resource(:file, @basepath+"/something").ref.should == resource.ref end @@ -594,7 +599,7 @@ describe Puppet::Resource::Catalog, "when compiling" do resource = Puppet::Type.type(:file).new :path => @basepath+"/something", :title => "other", :content => "blah" resource.expects(:isomorphic?).returns(false) @catalog.add_resource(resource) - @catalog.resource(:file, resource.title).should equal(resource) + @catalog.resource(:file, resource.title).must equal(resource) # We can't use .should here, because the resources respond to that method. raise "Aliased non-isomorphic resource" if @catalog.resource(:file, resource.name) end @@ -604,7 +609,7 @@ describe Puppet::Resource::Catalog, "when compiling" do resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog, :title => "/yay", :[] => "/yay" Puppet::Type.type(:file).expects(:new).with(args).returns(resource) @catalog.create_resource :file, args - @catalog.resource("File[/yay]").should equal(resource) + @catalog.resource("File[/yay]").must equal(resource) end describe "when adding resources with multiple namevars" do diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index aedd25f63..49973e346 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -20,7 +20,7 @@ describe Puppet::Resource do end it "should require the type and title" do - lambda { Puppet::Resource.new }.should raise_error(ArgumentError) + expect { Puppet::Resource.new }.to raise_error(ArgumentError) end it "should canonize types to capitalized strings" do @@ -93,15 +93,15 @@ describe Puppet::Resource do it "should fail if the title is nil and the type is not a valid resource reference string" do - expect { Puppet::Resource.new("resource-spec-foo") }.should raise_error(ArgumentError) + expect { Puppet::Resource.new("resource-spec-foo") }.to raise_error(ArgumentError) end it 'should fail if strict is set and type does not exist' do - expect { Puppet::Resource.new('resource-spec-foo', 'title', {:strict=>true}) }.should raise_error(ArgumentError, 'Invalid resource type resource-spec-foo') + expect { Puppet::Resource.new('resource-spec-foo', 'title', {:strict=>true}) }.to raise_error(ArgumentError, 'Invalid resource type resource-spec-foo') end it 'should fail if strict is set and class does not exist' do - expect { Puppet::Resource.new('Class', 'resource-spec-foo', {:strict=>true}) }.should raise_error(ArgumentError, 'Could not find declared class resource-spec-foo') + expect { Puppet::Resource.new('Class', 'resource-spec-foo', {:strict=>true}) }.to raise_error(ArgumentError, 'Could not find declared class resource-spec-foo') end it "should fail if the title is a hash and the type is not a valid resource reference string" do @@ -284,11 +284,11 @@ describe Puppet::Resource do end it "should fail if invalid parameters are used" do - expect { Puppet::Resource.new("file", "/path", :strict => true, :parameters => {:nosuchparam => "bar"}) }.should raise_error + expect { Puppet::Resource.new("file", "/path", :strict => true, :parameters => {:nosuchparam => "bar"}) }.to raise_error end it "should fail if the resource type cannot be resolved" do - expect { Puppet::Resource.new("nosuchtype", "/path", :strict => true) }.should raise_error + expect { Puppet::Resource.new("nosuchtype", "/path", :strict => true) }.to raise_error end end @@ -353,7 +353,7 @@ describe Puppet::Resource do it "should be able to set the name for non-builtin types" do resource = Puppet::Resource.new(:foo, "bar") resource[:name] = "eh" - expect { resource[:name] = "eh" }.should_not raise_error + expect { resource[:name] = "eh" }.to_not raise_error end it "should be able to return the name for non-builtin types" do @@ -445,7 +445,7 @@ describe Puppet::Resource do end it "should be able to be dumped to yaml" do - proc { YAML.dump(@resource) }.should_not raise_error + expect { YAML.dump(@resource) }.to_not raise_error end it "should produce an equivalent yaml object" do @@ -470,7 +470,7 @@ type: File end it "should deserialize a Puppet::Resource::Reference without exceptions" do - expect { YAML.load(@old_storedconfig_yaml) }.should_not raise_error + expect { YAML.load(@old_storedconfig_yaml) }.to_not raise_error end it "should deserialize as a Puppet::Resource::Reference as a Puppet::Resource" do @@ -486,7 +486,7 @@ type: File it "should use the resource type's :new method to create the resource if the resource is of a builtin type" do resource = Puppet::Resource.new("file", basepath+"/my/file") result = resource.to_ral - result.should be_instance_of(Puppet::Type.type(:file)) + result.must be_instance_of(Puppet::Type.type(:file)) result[:path].should == basepath+"/my/file" end @@ -494,7 +494,7 @@ type: File resource = Puppet::Resource.new("foobar", "somename") result = resource.to_ral - result.should be_instance_of(Puppet::Type.type(:component)) + result.must be_instance_of(Puppet::Type.type(:component)) result.title.should == "Foobar[somename]" end end @@ -735,12 +735,12 @@ type: File it "should fail if no title is provided" do @data.delete('title') - expect { Puppet::Resource.from_pson(@data) }.should raise_error(ArgumentError) + expect { Puppet::Resource.from_pson(@data) }.to raise_error(ArgumentError) end it "should fail if no type is provided" do @data.delete('type') - expect { Puppet::Resource.from_pson(@data) }.should raise_error(ArgumentError) + expect { Puppet::Resource.from_pson(@data) }.to raise_error(ArgumentError) end it "should set each of the provided parameters" do diff --git a/spec/unit/simple_graph_spec.rb b/spec/unit/simple_graph_spec.rb index 2cd00bda9..50f43c4aa 100755 --- a/spec/unit/simple_graph_spec.rb +++ b/spec/unit/simple_graph_spec.rb @@ -24,7 +24,7 @@ describe Puppet::SimpleGraph do @graph = Puppet::SimpleGraph.new @graph.add_edge(:one, :two) - proc { @graph.to_dot_graph }.should_not raise_error + expect { @graph.to_dot_graph }.to_not raise_error end describe "when managing vertices" do @@ -45,7 +45,7 @@ describe Puppet::SimpleGraph do it "should ignore already-present vertices when asked to add a vertex" do @graph.add_vertex(:test) - proc { @graph.add_vertex(:test) }.should_not raise_error + expect { @graph.add_vertex(:test) }.to_not raise_error end it "should return true when asked if a vertex is present" do @@ -72,7 +72,7 @@ describe Puppet::SimpleGraph do end it "should do nothing when a non-vertex is asked to be removed" do - proc { @graph.remove_vertex!(:one) }.should_not raise_error + expect { @graph.remove_vertex!(:one) }.to_not raise_error end end @@ -291,22 +291,22 @@ describe Puppet::SimpleGraph do it "should fail on two-vertex loops" do add_edges :a => :b, :b => :a - proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) + expect { @graph.report_cycles_in_graph }.to raise_error(Puppet::Error) end it "should fail on multi-vertex loops" do add_edges :a => :b, :b => :c, :c => :a - proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) + expect { @graph.report_cycles_in_graph }.to raise_error(Puppet::Error) end it "should fail when a larger tree contains a small cycle" do add_edges :a => :b, :b => :a, :c => :a, :d => :c - proc { @graph.report_cycles_in_graph }.should raise_error(Puppet::Error) + expect { @graph.report_cycles_in_graph }.to raise_error(Puppet::Error) end it "should succeed on trees with no cycles" do add_edges :a => :b, :b => :e, :c => :a, :d => :c - proc { @graph.report_cycles_in_graph }.should_not raise_error + expect { @graph.report_cycles_in_graph }.to_not raise_error end it "should produce the correct relationship text" do @@ -323,7 +323,7 @@ describe Puppet::SimpleGraph do add_edges "b" => "c" cycles = nil - expect { cycles = @graph.find_cycles_in_graph }.should_not raise_error + expect { cycles = @graph.find_cycles_in_graph }.to_not raise_error simplify(cycles).should be == [["a", "b"]] end @@ -332,7 +332,7 @@ describe Puppet::SimpleGraph do add_edges "b" => "b1", "b1" => "b" cycles = nil - expect { cycles = @graph.find_cycles_in_graph }.should_not raise_error + expect { cycles = @graph.find_cycles_in_graph }.to_not raise_error simplify(cycles).should be == [["a1", "a"], ["b1", "b"]] end @@ -342,7 +342,7 @@ describe Puppet::SimpleGraph do add_edges "c" => "c1", "c1" => "c2", "c2" => "c3", "c3" => "c" cycles = nil - expect { cycles = @graph.find_cycles_in_graph }.should_not raise_error + expect { cycles = @graph.find_cycles_in_graph }.to_not raise_error simplify(cycles).should be == [%w{a1 a}, %w{c1 c2 c3 c}] end @@ -353,7 +353,7 @@ describe Puppet::SimpleGraph do add_edges "c" => "c2", "c2" => "b" cycles = nil - expect { cycles = @graph.find_cycles_in_graph }.should_not raise_error + expect { cycles = @graph.find_cycles_in_graph }.to_not raise_error simplify(cycles).should be == [%w{a b c1 c2 c}] end @@ -362,7 +362,7 @@ describe Puppet::SimpleGraph do (1..(limit - 1)).each do |n| add_edges n.to_s => (n+1).to_s end cycles = nil - expect { cycles = @graph.find_cycles_in_graph }.should_not raise_error + expect { cycles = @graph.find_cycles_in_graph }.to_not raise_error simplify(cycles).should be == [] end diff --git a/spec/unit/ssl/certificate_authority/interface_spec.rb b/spec/unit/ssl/certificate_authority/interface_spec.rb index dd442104c..3e612161d 100755 --- a/spec/unit/ssl/certificate_authority/interface_spec.rb +++ b/spec/unit/ssl/certificate_authority/interface_spec.rb @@ -1,4 +1,4 @@ -#!/usr/bin/env rspec +#!/usr/bin/env ruby -S rspec require 'spec_helper' require 'puppet/ssl/certificate_authority' @@ -95,14 +95,14 @@ describe Puppet::SSL::CertificateAuthority::Interface do lambda { @applier.apply(@ca) }.should raise_error(Puppet::SSL::CertificateAuthority::Interface::InterfaceError) end - it "should log non-Interface failures rather than failing" do + it "should log non-Interface failures" do @applier = @class.new(:revoke, :to => :all) @ca.expects(:list).raises ArgumentError Puppet.expects(:err) - lambda { @applier.apply(@ca) }.should_not raise_error + lambda { @applier.apply(@ca) }.should raise_error end describe "with an empty array specified and the method is not list" do diff --git a/spec/unit/ssl/certificate_authority_spec.rb b/spec/unit/ssl/certificate_authority_spec.rb index 7fddeb3bc..c99491166 100755 --- a/spec/unit/ssl/certificate_authority_spec.rb +++ b/spec/unit/ssl/certificate_authority_spec.rb @@ -370,14 +370,15 @@ describe Puppet::SSL::CertificateAuthority do it "should fail if no CSR can be found for the host" do Puppet::SSL::CertificateRequest.indirection.expects(:find).with(@name).returns nil - lambda { @ca.sign(@name) }.should raise_error(ArgumentError) + expect { @ca.sign(@name) }.to raise_error(ArgumentError) end it "should fail if an unknown request extension is present" do @request.stubs :request_extensions => [{ "oid" => "bananas", "value" => "delicious" }] - expect { @ca.sign(@name) }. - should raise_error(/CSR has request extensions that are not permitted/) + expect { + @ca.sign(@name) + }.to raise_error(/CSR has request extensions that are not permitted/) end it "should fail if the CSR contains alt names and they are not expected" do @@ -390,7 +391,7 @@ describe Puppet::SSL::CertificateAuthority do it "should not fail if the CSR does not contain alt names and they are expected" do @request.stubs(:subject_alt_names).returns [] - expect { @ca.sign(@name, true) }.should_not raise_error + expect { @ca.sign(@name, true) }.to_not raise_error end it "should reject alt names by default" do @@ -705,7 +706,7 @@ describe Puppet::SSL::CertificateAuthority do describe "when applying a method to a set of hosts" do it "should fail if no subjects have been specified" do - lambda { @ca.apply(:generate) }.should raise_error(ArgumentError) + expect { @ca.apply(:generate) }.to raise_error(ArgumentError) end it "should create an Interface instance with the specified method and the options" do @@ -769,7 +770,7 @@ describe Puppet::SSL::CertificateAuthority do it "should raise an error if the certificate or CSR cannot be found" do Puppet::SSL::Certificate.indirection.expects(:find).with("myhost").returns nil Puppet::SSL::CertificateRequest.indirection.expects(:find).with("myhost").returns nil - lambda { @ca.fingerprint("myhost") }.should raise_error + expect { @ca.fingerprint("myhost") }.to raise_error end it "should try to find a CSR if no certificate can be found" do @@ -809,7 +810,7 @@ describe Puppet::SSL::CertificateAuthority do it "should fail if the host's certificate cannot be found" do Puppet::SSL::Certificate.indirection.expects(:find).with("me").returns(nil) - lambda { @ca.verify("me") }.should raise_error(ArgumentError) + expect { @ca.verify("me") }.to raise_error(ArgumentError) end it "should create an SSL Store to verify" do @@ -857,7 +858,7 @@ describe Puppet::SSL::CertificateAuthority do @store.expects(:verify).with("mycert").returns false - lambda { @ca.verify("me") }.should raise_error + expect { @ca.verify("me") }.to raise_error end end @@ -877,7 +878,7 @@ describe Puppet::SSL::CertificateAuthority do it "should fail if the certificate revocation list is disabled" do @ca.stubs(:crl).returns false - lambda { @ca.revoke('ca_testing') }.should raise_error(ArgumentError) + expect { @ca.revoke('ca_testing') }.to raise_error(ArgumentError) end @@ -923,7 +924,7 @@ describe Puppet::SSL::CertificateAuthority do it "should fail if a certificate already exists for the host" do Puppet::SSL::Certificate.indirection.expects(:find).with("him").returns "something" - lambda { @ca.generate("him") }.should raise_error(ArgumentError) + expect { @ca.generate("him") }.to raise_error(ArgumentError) end it "should create a new Host instance with the correct name" do diff --git a/spec/unit/transaction_spec.rb b/spec/unit/transaction_spec.rb index f5720e75a..9a1a38000 100755 --- a/spec/unit/transaction_spec.rb +++ b/spec/unit/transaction_spec.rb @@ -216,14 +216,14 @@ describe Puppet::Transaction do @transaction.eval_generate(resource) @filenames.each do |file| - @transaction.catalog.resource(:file, file).should be_a(Puppet::Type.type(:file)) + @transaction.catalog.resource(:file, file).must be_a(Puppet::Type.type(:file)) end end it "should add a sentinel whit for the resource" do @transaction.eval_generate(resource) - find_vertex(:whit, "completed_#{path}").should be_a(Puppet::Type.type(:whit)) + find_vertex(:whit, "completed_#{path}").must be_a(Puppet::Type.type(:whit)) end it "should replace dependencies on the resource with dependencies on the sentinel" do @@ -558,7 +558,7 @@ describe Puppet::Transaction do transaction.add_dynamically_generated_resources generated.each do |res| - res.should be_tagged(generator.tags) + res.must be_tagged(generator.tags) end end end diff --git a/spec/unit/type/cron_spec.rb b/spec/unit/type/cron_spec.rb index 7adafff48..b7731dbe1 100755 --- a/spec/unit/type/cron_spec.rb +++ b/spec/unit/type/cron_spec.rb @@ -38,25 +38,25 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? describe "ensure" do it "should support present as a value for ensure" do - proc { described_class.new(:name => 'foo', :ensure => :present) }.should_not raise_error + expect { described_class.new(:name => 'foo', :ensure => :present) }.to_not raise_error end it "should support absent as a value for ensure" do - proc { described_class.new(:name => 'foo', :ensure => :present) }.should_not raise_error + expect { described_class.new(:name => 'foo', :ensure => :present) }.to_not raise_error end it "should not support other values" do - proc { described_class.new(:name => 'foo', :ensure => :foo) }.should raise_error(Puppet::Error, /Invalid value/) + expect { described_class.new(:name => 'foo', :ensure => :foo) }.to raise_error(Puppet::Error, /Invalid value/) end end describe "minute" do it "should support absent" do - proc { described_class.new(:name => 'foo', :minute => 'absent') }.should_not raise_error + expect { described_class.new(:name => 'foo', :minute => 'absent') }.to_not raise_error end it "should support *" do - proc { described_class.new(:name => 'foo', :minute => '*') }.should_not raise_error + expect { described_class.new(:name => 'foo', :minute => '*') }.to_not raise_error end it "should translate absent to :absent" do @@ -68,62 +68,62 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? end it "should support valid single values" do - proc { described_class.new(:name => 'foo', :minute => '0') }.should_not raise_error - proc { described_class.new(:name => 'foo', :minute => '1') }.should_not raise_error - proc { described_class.new(:name => 'foo', :minute => '59') }.should_not raise_error + expect { described_class.new(:name => 'foo', :minute => '0') }.to_not raise_error + expect { described_class.new(:name => 'foo', :minute => '1') }.to_not raise_error + expect { described_class.new(:name => 'foo', :minute => '59') }.to_not raise_error end it "should not support non numeric characters" do - proc { described_class.new(:name => 'foo', :minute => 'z59') }.should raise_error(Puppet::Error, /z59 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '5z9') }.should raise_error(Puppet::Error, /5z9 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '59z') }.should raise_error(Puppet::Error, /59z is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => 'z59') }.to raise_error(Puppet::Error, /z59 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '5z9') }.to raise_error(Puppet::Error, /5z9 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '59z') }.to raise_error(Puppet::Error, /59z is not a valid minute/) end it "should not support single values out of range" do - proc { described_class.new(:name => 'foo', :minute => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '60') }.should raise_error(Puppet::Error, /60 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '61') }.should raise_error(Puppet::Error, /61 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '120') }.should raise_error(Puppet::Error, /120 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '60') }.to raise_error(Puppet::Error, /60 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '61') }.to raise_error(Puppet::Error, /61 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '120') }.to raise_error(Puppet::Error, /120 is not a valid minute/) end it "should support valid multiple values" do - proc { described_class.new(:name => 'foo', :minute => ['0','1','59'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :minute => ['40','30','20'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :minute => ['10','30','20'] ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :minute => ['0','1','59'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :minute => ['40','30','20'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :minute => ['10','30','20'] ) }.to_not raise_error end it "should not support multiple values if at least one is invalid" do # one invalid - proc { described_class.new(:name => 'foo', :minute => ['0','1','60'] ) }.should raise_error(Puppet::Error, /60 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => ['0','120','59'] ) }.should raise_error(Puppet::Error, /120 is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => ['-1','1','59'] ) }.should raise_error(Puppet::Error, /-1 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => ['0','1','60'] ) }.to raise_error(Puppet::Error, /60 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => ['0','120','59'] ) }.to raise_error(Puppet::Error, /120 is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => ['-1','1','59'] ) }.to raise_error(Puppet::Error, /-1 is not a valid minute/) # two invalid - proc { described_class.new(:name => 'foo', :minute => ['0','61','62'] ) }.should raise_error(Puppet::Error, /(61|62) is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => ['0','61','62'] ) }.to raise_error(Puppet::Error, /(61|62) is not a valid minute/) # all invalid - proc { described_class.new(:name => 'foo', :minute => ['-1','61','62'] ) }.should raise_error(Puppet::Error, /(-1|61|62) is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => ['-1','61','62'] ) }.to raise_error(Puppet::Error, /(-1|61|62) is not a valid minute/) end it "should support valid step syntax" do - proc { described_class.new(:name => 'foo', :minute => '*/2' ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :minute => '10-16/2' ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :minute => '*/2' ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :minute => '10-16/2' ) }.to_not raise_error end it "should not support invalid steps" do - proc { described_class.new(:name => 'foo', :minute => '*/A' ) }.should raise_error(Puppet::Error, /\*\/A is not a valid minute/) - proc { described_class.new(:name => 'foo', :minute => '*/2A' ) }.should raise_error(Puppet::Error, /\*\/2A is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '*/A' ) }.to raise_error(Puppet::Error, /\*\/A is not a valid minute/) + expect { described_class.new(:name => 'foo', :minute => '*/2A' ) }.to raise_error(Puppet::Error, /\*\/2A is not a valid minute/) # As it turns out cron does not complaining about steps that exceed the valid range - # proc { described_class.new(:name => 'foo', :minute => '*/120' ) }.should raise_error(Puppet::Error, /is not a valid minute/) + # expect { described_class.new(:name => 'foo', :minute => '*/120' ) }.to raise_error(Puppet::Error, /is not a valid minute/) end end describe "hour" do it "should support absent" do - proc { described_class.new(:name => 'foo', :hour => 'absent') }.should_not raise_error + expect { described_class.new(:name => 'foo', :hour => 'absent') }.to_not raise_error end it "should support *" do - proc { described_class.new(:name => 'foo', :hour => '*') }.should_not raise_error + expect { described_class.new(:name => 'foo', :hour => '*') }.to_not raise_error end it "should translate absent to :absent" do @@ -135,62 +135,62 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? end it "should support valid single values" do - proc { described_class.new(:name => 'foo', :hour => '0') }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => '11') }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => '12') }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => '13') }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => '23') }.should_not raise_error + expect { described_class.new(:name => 'foo', :hour => '0') }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => '11') }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => '12') }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => '13') }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => '23') }.to_not raise_error end it "should not support non numeric characters" do - proc { described_class.new(:name => 'foo', :hour => 'z15') }.should raise_error(Puppet::Error, /z15 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => '1z5') }.should raise_error(Puppet::Error, /1z5 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => '15z') }.should raise_error(Puppet::Error, /15z is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => 'z15') }.to raise_error(Puppet::Error, /z15 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '1z5') }.to raise_error(Puppet::Error, /1z5 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '15z') }.to raise_error(Puppet::Error, /15z is not a valid hour/) end it "should not support single values out of range" do - proc { described_class.new(:name => 'foo', :hour => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => '24') }.should raise_error(Puppet::Error, /24 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => '120') }.should raise_error(Puppet::Error, /120 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '24') }.to raise_error(Puppet::Error, /24 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '120') }.to raise_error(Puppet::Error, /120 is not a valid hour/) end it "should support valid multiple values" do - proc { described_class.new(:name => 'foo', :hour => ['0','1','23'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => ['5','16','14'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => ['16','13','9'] ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :hour => ['0','1','23'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => ['5','16','14'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => ['16','13','9'] ) }.to_not raise_error end it "should not support multiple values if at least one is invalid" do # one invalid - proc { described_class.new(:name => 'foo', :hour => ['0','1','24'] ) }.should raise_error(Puppet::Error, /24 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => ['0','-1','5'] ) }.should raise_error(Puppet::Error, /-1 is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => ['-1','1','23'] ) }.should raise_error(Puppet::Error, /-1 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => ['0','1','24'] ) }.to raise_error(Puppet::Error, /24 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => ['0','-1','5'] ) }.to raise_error(Puppet::Error, /-1 is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => ['-1','1','23'] ) }.to raise_error(Puppet::Error, /-1 is not a valid hour/) # two invalid - proc { described_class.new(:name => 'foo', :hour => ['0','25','26'] ) }.should raise_error(Puppet::Error, /(25|26) is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => ['0','25','26'] ) }.to raise_error(Puppet::Error, /(25|26) is not a valid hour/) # all invalid - proc { described_class.new(:name => 'foo', :hour => ['-1','24','120'] ) }.should raise_error(Puppet::Error, /(-1|24|120) is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => ['-1','24','120'] ) }.to raise_error(Puppet::Error, /(-1|24|120) is not a valid hour/) end it "should support valid step syntax" do - proc { described_class.new(:name => 'foo', :hour => '*/2' ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :hour => '10-18/4' ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :hour => '*/2' ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :hour => '10-18/4' ) }.to_not raise_error end it "should not support invalid steps" do - proc { described_class.new(:name => 'foo', :hour => '*/A' ) }.should raise_error(Puppet::Error, /\*\/A is not a valid hour/) - proc { described_class.new(:name => 'foo', :hour => '*/2A' ) }.should raise_error(Puppet::Error, /\*\/2A is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '*/A' ) }.to raise_error(Puppet::Error, /\*\/A is not a valid hour/) + expect { described_class.new(:name => 'foo', :hour => '*/2A' ) }.to raise_error(Puppet::Error, /\*\/2A is not a valid hour/) # As it turns out cron does not complaining about steps that exceed the valid range - # proc { described_class.new(:name => 'foo', :hour => '*/26' ) }.should raise_error(Puppet::Error, /is not a valid hour/) + # expect { described_class.new(:name => 'foo', :hour => '*/26' ) }.to raise_error(Puppet::Error, /is not a valid hour/) end end describe "weekday" do it "should support absent" do - proc { described_class.new(:name => 'foo', :weekday => 'absent') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'absent') }.to_not raise_error end it "should support *" do - proc { described_class.new(:name => 'foo', :weekday => '*') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '*') }.to_not raise_error end it "should translate absent to :absent" do @@ -202,78 +202,78 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? end it "should support valid numeric weekdays" do - proc { described_class.new(:name => 'foo', :weekday => '0') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => '1') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => '6') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '0') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '1') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '6') }.to_not raise_error # According to http://www.manpagez.com/man/5/crontab 7 is also valid (Sunday) - proc { described_class.new(:name => 'foo', :weekday => '7') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '7') }.to_not raise_error end it "should support valid weekdays as words (long version)" do - proc { described_class.new(:name => 'foo', :weekday => 'Monday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Tuesday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Wednesday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Thursday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Friday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Saturday') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Sunday') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Monday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Tuesday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Wednesday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Thursday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Friday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Saturday') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Sunday') }.to_not raise_error end it "should support valid weekdays as words (3 character version)" do - proc { described_class.new(:name => 'foo', :weekday => 'Mon') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Tue') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Wed') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Thu') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Fri') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Sat') }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => 'Sun') }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Mon') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Tue') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Wed') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Thu') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Fri') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Sat') }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => 'Sun') }.to_not raise_error end it "should not support numeric values out of range" do - proc { described_class.new(:name => 'foo', :weekday => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid weekday/) - proc { described_class.new(:name => 'foo', :weekday => '8') }.should raise_error(Puppet::Error, /8 is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => '8') }.to raise_error(Puppet::Error, /8 is not a valid weekday/) end it "should not support invalid weekday names" do - proc { described_class.new(:name => 'foo', :weekday => 'Sar') }.should raise_error(Puppet::Error, /Sar is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => 'Sar') }.to raise_error(Puppet::Error, /Sar is not a valid weekday/) end it "should support valid multiple values" do - proc { described_class.new(:name => 'foo', :weekday => ['0','1','6'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => ['Mon','Wed','Friday'] ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => ['0','1','6'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => ['Mon','Wed','Friday'] ) }.to_not raise_error end it "should not support multiple values if at least one is invalid" do # one invalid - proc { described_class.new(:name => 'foo', :weekday => ['0','1','8'] ) }.should raise_error(Puppet::Error, /8 is not a valid weekday/) - proc { described_class.new(:name => 'foo', :weekday => ['Mon','Fii','Sat'] ) }.should raise_error(Puppet::Error, /Fii is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => ['0','1','8'] ) }.to raise_error(Puppet::Error, /8 is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => ['Mon','Fii','Sat'] ) }.to raise_error(Puppet::Error, /Fii is not a valid weekday/) # two invalid - proc { described_class.new(:name => 'foo', :weekday => ['Mos','Fii','Sat'] ) }.should raise_error(Puppet::Error, /(Mos|Fii) is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => ['Mos','Fii','Sat'] ) }.to raise_error(Puppet::Error, /(Mos|Fii) is not a valid weekday/) # all invalid - proc { described_class.new(:name => 'foo', :weekday => ['Mos','Fii','Saa'] ) }.should raise_error(Puppet::Error, /(Mos|Fii|Saa) is not a valid weekday/) - proc { described_class.new(:name => 'foo', :weekday => ['-1','8','11'] ) }.should raise_error(Puppet::Error, /(-1|8|11) is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => ['Mos','Fii','Saa'] ) }.to raise_error(Puppet::Error, /(Mos|Fii|Saa) is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => ['-1','8','11'] ) }.to raise_error(Puppet::Error, /(-1|8|11) is not a valid weekday/) end it "should support valid step syntax" do - proc { described_class.new(:name => 'foo', :weekday => '*/2' ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :weekday => '0-4/2' ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '*/2' ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :weekday => '0-4/2' ) }.to_not raise_error end it "should not support invalid steps" do - proc { described_class.new(:name => 'foo', :weekday => '*/A' ) }.should raise_error(Puppet::Error, /\*\/A is not a valid weekday/) - proc { described_class.new(:name => 'foo', :weekday => '*/2A' ) }.should raise_error(Puppet::Error, /\*\/2A is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => '*/A' ) }.to raise_error(Puppet::Error, /\*\/A is not a valid weekday/) + expect { described_class.new(:name => 'foo', :weekday => '*/2A' ) }.to raise_error(Puppet::Error, /\*\/2A is not a valid weekday/) # As it turns out cron does not complaining about steps that exceed the valid range - # proc { described_class.new(:name => 'foo', :weekday => '*/9' ) }.should raise_error(Puppet::Error, /is not a valid weekday/) + # expect { described_class.new(:name => 'foo', :weekday => '*/9' ) }.to raise_error(Puppet::Error, /is not a valid weekday/) end end describe "month" do it "should support absent" do - proc { described_class.new(:name => 'foo', :month => 'absent') }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => 'absent') }.to_not raise_error end it "should support *" do - proc { described_class.new(:name => 'foo', :month => '*') }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => '*') }.to_not raise_error end it "should translate absent to :absent" do @@ -285,95 +285,95 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? end it "should support valid numeric values" do - proc { described_class.new(:name => 'foo', :month => '1') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => '12') }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => '1') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => '12') }.to_not raise_error end it "should support valid months as words" do - proc { described_class.new(:name => 'foo', :month => 'January') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'February') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'March') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'April') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'May') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'June') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'July') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'August') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'September') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'October') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'November') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'December') }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => 'January') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'February') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'March') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'April') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'May') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'June') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'July') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'August') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'September') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'October') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'November') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'December') }.to_not raise_error end it "should support valid months as words (3 character short version)" do - proc { described_class.new(:name => 'foo', :month => 'Jan') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Feb') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Mar') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Apr') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'May') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Jun') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Jul') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Aug') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Sep') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Oct') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Nov') }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => 'Dec') }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Jan') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Feb') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Mar') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Apr') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'May') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Jun') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Jul') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Aug') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Sep') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Oct') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Nov') }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => 'Dec') }.to_not raise_error end it "should not support numeric values out of range" do - proc { described_class.new(:name => 'foo', :month => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '0') }.should raise_error(Puppet::Error, /0 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '13') }.should raise_error(Puppet::Error, /13 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '0') }.to raise_error(Puppet::Error, /0 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '13') }.to raise_error(Puppet::Error, /13 is not a valid month/) end it "should not support words that are not valid months" do - proc { described_class.new(:name => 'foo', :month => 'Jal') }.should raise_error(Puppet::Error, /Jal is not a valid month/) + expect { described_class.new(:name => 'foo', :month => 'Jal') }.to raise_error(Puppet::Error, /Jal is not a valid month/) end it "should not support single values out of range" do - proc { described_class.new(:name => 'foo', :month => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '60') }.should raise_error(Puppet::Error, /60 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '61') }.should raise_error(Puppet::Error, /61 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '120') }.should raise_error(Puppet::Error, /120 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '60') }.to raise_error(Puppet::Error, /60 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '61') }.to raise_error(Puppet::Error, /61 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '120') }.to raise_error(Puppet::Error, /120 is not a valid month/) end it "should support valid multiple values" do - proc { described_class.new(:name => 'foo', :month => ['1','9','12'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => ['Jan','March','Jul'] ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => ['1','9','12'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => ['Jan','March','Jul'] ) }.to_not raise_error end it "should not support multiple values if at least one is invalid" do # one invalid - proc { described_class.new(:name => 'foo', :month => ['0','1','12'] ) }.should raise_error(Puppet::Error, /0 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => ['1','13','10'] ) }.should raise_error(Puppet::Error, /13 is not a valid month/) - proc { described_class.new(:name => 'foo', :month => ['Jan','Feb','Jxx'] ) }.should raise_error(Puppet::Error, /Jxx is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['0','1','12'] ) }.to raise_error(Puppet::Error, /0 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['1','13','10'] ) }.to raise_error(Puppet::Error, /13 is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['Jan','Feb','Jxx'] ) }.to raise_error(Puppet::Error, /Jxx is not a valid month/) # two invalid - proc { described_class.new(:name => 'foo', :month => ['Jan','Fex','Jux'] ) }.should raise_error(Puppet::Error, /(Fex|Jux) is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['Jan','Fex','Jux'] ) }.to raise_error(Puppet::Error, /(Fex|Jux) is not a valid month/) # all invalid - proc { described_class.new(:name => 'foo', :month => ['-1','0','13'] ) }.should raise_error(Puppet::Error, /(-1|0|13) is not a valid month/) - proc { described_class.new(:name => 'foo', :month => ['Jax','Fex','Aux'] ) }.should raise_error(Puppet::Error, /(Jax|Fex|Aux) is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['-1','0','13'] ) }.to raise_error(Puppet::Error, /(-1|0|13) is not a valid month/) + expect { described_class.new(:name => 'foo', :month => ['Jax','Fex','Aux'] ) }.to raise_error(Puppet::Error, /(Jax|Fex|Aux) is not a valid month/) end it "should support valid step syntax" do - proc { described_class.new(:name => 'foo', :month => '*/2' ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :month => '1-12/3' ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :month => '*/2' ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :month => '1-12/3' ) }.to_not raise_error end it "should not support invalid steps" do - proc { described_class.new(:name => 'foo', :month => '*/A' ) }.should raise_error(Puppet::Error, /\*\/A is not a valid month/) - proc { described_class.new(:name => 'foo', :month => '*/2A' ) }.should raise_error(Puppet::Error, /\*\/2A is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '*/A' ) }.to raise_error(Puppet::Error, /\*\/A is not a valid month/) + expect { described_class.new(:name => 'foo', :month => '*/2A' ) }.to raise_error(Puppet::Error, /\*\/2A is not a valid month/) # As it turns out cron does not complaining about steps that exceed the valid range - # proc { described_class.new(:name => 'foo', :month => '*/13' ) }.should raise_error(Puppet::Error, /is not a valid month/) + # expect { described_class.new(:name => 'foo', :month => '*/13' ) }.to raise_error(Puppet::Error, /is not a valid month/) end end describe "monthday" do it "should support absent" do - proc { described_class.new(:name => 'foo', :monthday => 'absent') }.should_not raise_error + expect { described_class.new(:name => 'foo', :monthday => 'absent') }.to_not raise_error end it "should support *" do - proc { described_class.new(:name => 'foo', :monthday => '*') }.should_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '*') }.to_not raise_error end it "should translate absent to :absent" do @@ -385,76 +385,76 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? end it "should support valid single values" do - proc { described_class.new(:name => 'foo', :monthday => '1') }.should_not raise_error - proc { described_class.new(:name => 'foo', :monthday => '30') }.should_not raise_error - proc { described_class.new(:name => 'foo', :monthday => '31') }.should_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '1') }.to_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '30') }.to_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '31') }.to_not raise_error end it "should not support non numeric characters" do - proc { described_class.new(:name => 'foo', :monthday => 'z23') }.should raise_error(Puppet::Error, /z23 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => '2z3') }.should raise_error(Puppet::Error, /2z3 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => '23z') }.should raise_error(Puppet::Error, /23z is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => 'z23') }.to raise_error(Puppet::Error, /z23 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '2z3') }.to raise_error(Puppet::Error, /2z3 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '23z') }.to raise_error(Puppet::Error, /23z is not a valid monthday/) end it "should not support single values out of range" do - proc { described_class.new(:name => 'foo', :monthday => '-1') }.should raise_error(Puppet::Error, /-1 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => '0') }.should raise_error(Puppet::Error, /0 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => '32') }.should raise_error(Puppet::Error, /32 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '-1') }.to raise_error(Puppet::Error, /-1 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '0') }.to raise_error(Puppet::Error, /0 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '32') }.to raise_error(Puppet::Error, /32 is not a valid monthday/) end it "should support valid multiple values" do - proc { described_class.new(:name => 'foo', :monthday => ['1','23','31'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :monthday => ['31','23','1'] ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :monthday => ['1','31','23'] ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :monthday => ['1','23','31'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :monthday => ['31','23','1'] ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :monthday => ['1','31','23'] ) }.to_not raise_error end it "should not support multiple values if at least one is invalid" do # one invalid - proc { described_class.new(:name => 'foo', :monthday => ['1','23','32'] ) }.should raise_error(Puppet::Error, /32 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => ['-1','12','23'] ) }.should raise_error(Puppet::Error, /-1 is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => ['13','32','30'] ) }.should raise_error(Puppet::Error, /32 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => ['1','23','32'] ) }.to raise_error(Puppet::Error, /32 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => ['-1','12','23'] ) }.to raise_error(Puppet::Error, /-1 is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => ['13','32','30'] ) }.to raise_error(Puppet::Error, /32 is not a valid monthday/) # two invalid - proc { described_class.new(:name => 'foo', :monthday => ['-1','0','23'] ) }.should raise_error(Puppet::Error, /(-1|0) is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => ['-1','0','23'] ) }.to raise_error(Puppet::Error, /(-1|0) is not a valid monthday/) # all invalid - proc { described_class.new(:name => 'foo', :monthday => ['-1','0','32'] ) }.should raise_error(Puppet::Error, /(-1|0|32) is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => ['-1','0','32'] ) }.to raise_error(Puppet::Error, /(-1|0|32) is not a valid monthday/) end it "should support valid step syntax" do - proc { described_class.new(:name => 'foo', :monthday => '*/2' ) }.should_not raise_error - proc { described_class.new(:name => 'foo', :monthday => '10-16/2' ) }.should_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '*/2' ) }.to_not raise_error + expect { described_class.new(:name => 'foo', :monthday => '10-16/2' ) }.to_not raise_error end it "should not support invalid steps" do - proc { described_class.new(:name => 'foo', :monthday => '*/A' ) }.should raise_error(Puppet::Error, /\*\/A is not a valid monthday/) - proc { described_class.new(:name => 'foo', :monthday => '*/2A' ) }.should raise_error(Puppet::Error, /\*\/2A is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '*/A' ) }.to raise_error(Puppet::Error, /\*\/A is not a valid monthday/) + expect { described_class.new(:name => 'foo', :monthday => '*/2A' ) }.to raise_error(Puppet::Error, /\*\/2A is not a valid monthday/) # As it turns out cron does not complaining about steps that exceed the valid range - # proc { described_class.new(:name => 'foo', :monthday => '*/32' ) }.should raise_error(Puppet::Error, /is not a valid monthday/) + # expect { described_class.new(:name => 'foo', :monthday => '*/32' ) }.to raise_error(Puppet::Error, /is not a valid monthday/) end end describe "environment" do it "it should accept an :environment that looks like a path" do - lambda do + expect do described_class.new(:name => 'foo',:environment => 'PATH=/bin:/usr/bin:/usr/sbin') - end.should_not raise_error + end.to_not raise_error end it "should not accept environment variables that do not contain '='" do - lambda do + expect do described_class.new(:name => 'foo',:environment => 'INVALID') - end.should raise_error(Puppet::Error, /Invalid environment setting "INVALID"/) + end.to raise_error(Puppet::Error, /Invalid environment setting "INVALID"/) end it "should accept empty environment variables that do not contain '='" do - lambda do + expect do described_class.new(:name => 'foo',:environment => 'MAILTO=') - end.should_not raise_error(Puppet::Error) + end.to_not raise_error(Puppet::Error) end it "should accept 'absent'" do - lambda do + expect do described_class.new(:name => 'foo',:environment => 'absent') - end.should_not raise_error(Puppet::Error) + end.to_not raise_error(Puppet::Error) end end @@ -481,7 +481,7 @@ describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? it "should require a command when adding an entry" do entry = described_class.new(:name => "test_entry", :ensure => :present) - expect { entry.value(:command) }.should raise_error(Puppet::Error, /No command/) + expect { entry.value(:command) }.to raise_error(Puppet::Error, /No command/) end it "should not require a command when removing an entry" do diff --git a/spec/unit/type/exec_spec.rb b/spec/unit/type/exec_spec.rb index 3bb607b4b..6f7447978 100755 --- a/spec/unit/type/exec_spec.rb +++ b/spec/unit/type/exec_spec.rb @@ -59,17 +59,17 @@ describe Puppet::Type.type(:exec) do end it "should report a failure" do - proc { exec_tester('false', 1).refresh }. - should raise_error(Puppet::Error, /^false returned 1 instead of/) + expect { exec_tester('false', 1).refresh }. + to raise_error(Puppet::Error, /^false returned 1 instead of/) end it "should not report a failure if the exit status is specified in a returns array" do - proc { exec_tester("false", 1, :returns => [0, 1]).refresh }.should_not raise_error + expect { exec_tester("false", 1, :returns => [0, 1]).refresh }.to_not raise_error end it "should report a failure if the exit status is not specified in a returns array" do - proc { exec_tester('false', 1, :returns => [0, 100]).refresh }. - should raise_error(Puppet::Error, /^false returned 1 instead of/) + expect { exec_tester('false', 1, :returns => [0, 100]).refresh }. + to raise_error(Puppet::Error, /^false returned 1 instead of/) end it "should log the output on success" do @@ -84,8 +84,8 @@ describe Puppet::Type.type(:exec) do it "should log the output on failure" do output = "output1\noutput2\n" - proc { exec_tester('false', 1, :output => output, :logoutput => true).refresh }. - should raise_error(Puppet::Error) + expect { exec_tester('false', 1, :output => output, :logoutput => true).refresh }. + to raise_error(Puppet::Error) output.split("\n").each do |line| log = @logs.shift @@ -98,8 +98,8 @@ describe Puppet::Type.type(:exec) do describe "when logoutput=>on_failure is set" do it "should log the output on failure" do output = "output1\noutput2\n" - proc { exec_tester('false', 1, :output => output, :logoutput => :on_failure).refresh }. - should raise_error(Puppet::Error, /^false returned 1 instead of/) + expect { exec_tester('false', 1, :output => output, :logoutput => :on_failure).refresh }. + to raise_error(Puppet::Error, /^false returned 1 instead of/) output.split("\n").each do |line| log = @logs.shift @@ -111,10 +111,10 @@ describe Puppet::Type.type(:exec) do it "should log the output on failure when returns is specified as an array" do output = "output1\noutput2\n" - proc { + expect { exec_tester('false', 1, :output => output, :returns => [0, 100], :logoutput => :on_failure).refresh - }.should raise_error(Puppet::Error, /^false returned 1 instead of/) + }.to raise_error(Puppet::Error, /^false returned 1 instead of/) output.split("\n").each do |line| log = @logs.shift @@ -138,7 +138,7 @@ describe Puppet::Type.type(:exec) do it "should repeat the command attempt 'tries' times on failure and produce an error" do tries = 5 resource = exec_tester("false", 1, :tries => tries, :try_sleep => 0) - proc { resource.refresh }.should raise_error(Puppet::Error) + expect { resource.refresh }.to raise_error(Puppet::Error) end end end @@ -190,8 +190,9 @@ describe Puppet::Type.type(:exec) do describe "on POSIX systems", :as_platform => :posix do it "should fail if we are not root" do Puppet.features.stubs(:root?).returns(false) - expect { Puppet::Type.type(:exec).new(:name => '/bin/true whatever', :user => 'input') }. - should raise_error Puppet::Error, /Parameter user failed/ + expect { + Puppet::Type.type(:exec).new(:name => '/bin/true whatever', :user => 'input') + }.to raise_error Puppet::Error, /Parameter user failed/ end ['one', 2, 'root', 4294967295, 4294967296].each do |value| @@ -209,8 +210,9 @@ describe Puppet::Type.type(:exec) do end it "should reject user parameter" do - expect { Puppet::Type.type(:exec).new(:name => 'c:\windows\notepad.exe', :user => 'input') }. - should raise_error Puppet::Error, /Unable to execute commands as other users on Windows/ + expect { + Puppet::Type.type(:exec).new(:name => 'c:\windows\notepad.exe', :user => 'input') + }.to raise_error Puppet::Error, /Unable to execute commands as other users on Windows/ end end end @@ -267,12 +269,12 @@ describe Puppet::Type.type(:exec) do end it "should work if the provider calls the command valid" do - expect { test(command, true) }.should_not raise_error + expect { test(command, true) }.to_not raise_error end it "should fail if the provider calls the command invalid" do expect { test(command, false) }. - should raise_error Puppet::Error, /Parameter #{@param} failed: from a stub/ + to raise_error Puppet::Error, /Parameter #{@param} failed: from a stub/ end end end @@ -335,7 +337,7 @@ describe Puppet::Type.type(:exec) do }.each do |name, data| it "should reject #{name} without assignment" do expect { @exec[:environment] = data }. - should raise_error Puppet::Error, /Invalid environment setting/ + to raise_error Puppet::Error, /Invalid environment setting/ end end end @@ -356,12 +358,12 @@ describe Puppet::Type.type(:exec) do ['1/2', '', 'foo', '5foo'].each do |invalid| it "should reject '#{invalid}' as invalid" do expect { @exec[:timeout] = invalid }. - should raise_error Puppet::Error, /The timeout must be a number/ + to raise_error Puppet::Error, /The timeout must be a number/ end it "should reject '#{invalid}' in an array as invalid" do expect { @exec[:timeout] = [invalid] }. - should raise_error Puppet::Error, /The timeout must be a number/ + to raise_error Puppet::Error, /The timeout must be a number/ end end @@ -376,7 +378,7 @@ describe Puppet::Type.type(:exec) do FileTest.stubs(:executable?).with(File.expand_path('/bin/sleep')).returns(true) sleep_exec = Puppet::Type.type(:exec).new(:name => 'sleep 1', :path => [File.expand_path('/bin')], :timeout => '0.2') - lambda { sleep_exec.refresh }.should raise_error Puppet::Error, "Command exceeded timeout" + expect { sleep_exec.refresh }.to raise_error Puppet::Error, "Command exceeded timeout" end it "should convert timeout to a float" do @@ -413,14 +415,14 @@ describe Puppet::Type.type(:exec) do [-3.5, -1, 0, 0.2, '1/2', '1_000_000', '+12', '', 'foo'].each do |invalid| it "should reject '#{invalid}' as invalid" do expect { @exec[:tries] = invalid }. - should raise_error Puppet::Error, /Tries must be an integer/ + to raise_error Puppet::Error, /Tries must be an integer/ end if "REVISIT: too much test log spam" == "a good thing" then it "should reject '#{invalid}' in an array as invalid" do pending "inconsistent, but this is not supporting arrays, unlike timeout" expect { @exec[:tries] = [invalid] }. - should raise_error Puppet::Error, /Tries must be an integer/ + to raise_error Puppet::Error, /Tries must be an integer/ end end end @@ -452,14 +454,14 @@ describe Puppet::Type.type(:exec) do }.each do |invalid, error| it "should reject '#{invalid}' as invalid" do expect { @exec[:try_sleep] = invalid }. - should raise_error Puppet::Error, /try_sleep #{error}/ + to raise_error Puppet::Error, /try_sleep #{error}/ end if "REVISIT: too much test log spam" == "a good thing" then it "should reject '#{invalid}' in an array as invalid" do pending "inconsistent, but this is not supporting arrays, unlike timeout" expect { @exec[:try_sleep] = [invalid] }. - should raise_error Puppet::Error, /try_sleep #{error}/ + to raise_error Puppet::Error, /try_sleep #{error}/ end end end @@ -476,7 +478,7 @@ describe Puppet::Type.type(:exec) do [1, 0, "1", "0", "yes", "y", "no", "n"].each do |value| it "should reject '#{value}'" do expect { @exec[:refreshonly] = value }. - should raise_error(Puppet::Error, + to raise_error(Puppet::Error, /Invalid value #{value.inspect}\. Valid values are true, false/ ) end diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb index fee7e552c..b2e4ed2d6 100755 --- a/spec/unit/type/file_spec.rb +++ b/spec/unit/type/file_spec.rb @@ -42,7 +42,7 @@ describe Puppet::Type.type(:file) do # REVISIT: This should be wrong, later. See the next test. # --daniel 2011-01-31 file[:path].should == '/tmp/xxx' - }.should_not raise_error + }.to_not raise_error end # REVISIT: This is pending, because I don't want to try and audit the @@ -76,7 +76,7 @@ describe Puppet::Type.type(:file) do end it "should not accept a drive letter without a slash", :'fails_on_ruby_1.9.2' => true do - lambda { file[:path] = "X:" }.should raise_error(/File paths must be fully qualified/) + expect { file[:path] = "X:" }.to raise_error(/File paths must be fully qualified/) end describe "when using UNC filenames", :if => Puppet.features.microsoft_windows?, :'fails_on_ruby_1.9.2' => true do @@ -433,7 +433,7 @@ describe Puppet::Type.type(:file) do it "should set a desired 'ensure' value if none is set and 'target' is set" do file = described_class.new(:path => path, :target => File.expand_path(__FILE__)) - file[:ensure].should == :symlink + file[:ensure].should == :link end end @@ -465,7 +465,7 @@ describe Puppet::Type.type(:file) do it "should create a new resource relative to the parent" do child = file.newchild('bar') - child.should be_a(described_class) + child.must be_a(described_class) child[:path].should == File.join(file[:path], 'bar') end @@ -1112,6 +1112,15 @@ describe Puppet::Type.type(:file) do File.chmod(0777, dir) end + it "should return nil if parts of path are no directories" do + regular_file = tmpfile('ENOTDIR_test') + FileUtils.touch(regular_file) + impossible_child = File.join(regular_file, 'some_file') + + file[:path] = impossible_child + file.stat.should be_nil + end + it "should return the stat instance" do file.stat.should be_a(File::Stat) end @@ -1133,7 +1142,7 @@ describe Puppet::Type.type(:file) do property = stub('content_property', :actual_content => "something", :length => "something".length) file.stubs(:property).with(:content).returns(property) - lambda { file.write(:content) }.should raise_error(Puppet::Error) + expect { file.write(:content) }.to raise_error(Puppet::Error) end it "should delegate writing to the content property" do @@ -1161,7 +1170,7 @@ describe Puppet::Type.type(:file) do property = stub('content_property', :actual_content => "something", :length => "something".length, :write => 'checksum_a') file.stubs(:property).with(:content).returns(property) - lambda { file.write :NOTUSED }.should raise_error(Puppet::Error) + expect { file.write :NOTUSED }.to raise_error(Puppet::Error) end end @@ -1175,7 +1184,7 @@ describe Puppet::Type.type(:file) do property = stub('content_property', :actual_content => "something", :length => "something".length, :write => 'checksum_a') file.stubs(:property).with(:content).returns(property) - lambda { file.write :NOTUSED }.should_not raise_error(Puppet::Error) + expect { file.write :NOTUSED }.to_not raise_error(Puppet::Error) end end end @@ -1260,7 +1269,7 @@ describe Puppet::Type.type(:file) do describe "target" do it "should require file resource when specified with the target property" do file = described_class.new(:path => File.expand_path("/foo"), :ensure => :directory) - link = described_class.new(:path => File.expand_path("/bar"), :ensure => :symlink, :target => File.expand_path("/foo")) + link = described_class.new(:path => File.expand_path("/bar"), :ensure => :link, :target => File.expand_path("/foo")) catalog.add_resource file catalog.add_resource link reqs = link.autorequire @@ -1281,7 +1290,7 @@ describe Puppet::Type.type(:file) do end it "should not require target if target is not managed" do - link = described_class.new(:path => File.expand_path('/foo'), :ensure => :symlink, :target => '/bar') + link = described_class.new(:path => File.expand_path('/foo'), :ensure => :link, :target => '/bar') catalog.add_resource link link.autorequire.size.should == 0 end @@ -1420,7 +1429,7 @@ describe Puppet::Type.type(:file) do it 'should validate' do - lambda { file.validate }.should_not raise_error + expect { file.validate }.to_not raise_error end end end @@ -1431,7 +1440,7 @@ describe Puppet::Type.type(:file) do end it 'should raise an exception when validating' do - lambda { file.validate }.should raise_error(/You cannot specify source when using checksum 'none'/) + expect { file.validate }.to raise_error(/You cannot specify source when using checksum 'none'/) end end end @@ -1448,7 +1457,7 @@ describe Puppet::Type.type(:file) do end it 'should validate' do - lambda { file.validate }.should_not raise_error + expect { file.validate }.to_not raise_error end end end @@ -1458,7 +1467,7 @@ describe Puppet::Type.type(:file) do it 'should raise an exception when validating' do file[:checksum] = checksum_type - lambda { file.validate }.should raise_error(/You cannot specify content when using checksum '#{checksum_type}'/) + expect { file.validate }.to raise_error(/You cannot specify content when using checksum '#{checksum_type}'/) end end end diff --git a/spec/unit/type/interface_spec.rb b/spec/unit/type/interface_spec.rb index 74e3257f6..ad54d3084 100755 --- a/spec/unit/type/interface_spec.rb +++ b/spec/unit/type/interface_spec.rb @@ -16,7 +16,7 @@ describe Puppet::Type.type(:interface) do end it "should be applied on device" do - Puppet::Type.type(:interface).new(:name => "FastEthernet 0/1").should be_appliable_to_device + Puppet::Type.type(:interface).new(:name => "FastEthernet 0/1").must be_appliable_to_device end [:description, :speed, :duplex, :native_vlan, :encapsulation, :mode, :allowed_trunk_vlans, :etherchannel, :ipaddress].each do |p| diff --git a/spec/unit/type/scheduled_task_spec.rb b/spec/unit/type/scheduled_task_spec.rb index 17d84900e..75b9c02bf 100644 --- a/spec/unit/type/scheduled_task_spec.rb +++ b/spec/unit/type/scheduled_task_spec.rb @@ -15,6 +15,20 @@ describe Puppet::Type.type(:scheduled_task), :if => Puppet.features.microsoft_wi described_class.new(:name => 'Test Task', :command => 'C:\Windows\System32\notepad.exe')[:command].should == 'C:\Windows\System32\notepad.exe' end + it 'should convert forward slashes to backslashes' do + described_class.new( + :name => 'Test Task', + :command => 'C:/Windows/System32/notepad.exe' + )[:command].should == 'C:\Windows\System32\notepad.exe' + end + + it 'should normalize backslashes' do + described_class.new( + :name => 'Test Task', + :command => 'C:\Windows\\System32\\\\notepad.exe' + )[:command].should == 'C:\Windows\System32\notepad.exe' + end + it 'should fail if the path to the command is not absolute' do expect { described_class.new(:name => 'Test Task', :command => 'notepad.exe') @@ -26,25 +40,12 @@ describe Puppet::Type.type(:scheduled_task), :if => Puppet.features.microsoft_wi end describe 'when setting the command arguments' do - it 'should fail if provided an array' do - expect { - described_class.new( - :name => 'Test Task', - :command => 'C:\Windows\System32\notepad.exe', - :arguments => ['/a', '/b', '/c'] - ) - }.to raise_error( - Puppet::Error, - /Parameter arguments failed: Must be specified as a single string/ - ) - end - it 'should accept a string' do described_class.new( :name => 'Test Task', :command => 'C:\Windows\System32\notepad.exe', :arguments => '/a /b /c' - )[:arguments].should == ['/a /b /c'] + )[:arguments].should == '/a /b /c' end it 'should allow not specifying any command arguments' do diff --git a/spec/unit/type/tidy_spec.rb b/spec/unit/type/tidy_spec.rb index bf892e836..881805aa2 100755 --- a/spec/unit/type/tidy_spec.rb +++ b/spec/unit/type/tidy_spec.rb @@ -372,7 +372,7 @@ describe tidy do @tidy.parameter(:size).stubs(:tidy?).returns true @tidy.parameter(:age).stubs(:tidy?).returns false - @tidy.should be_tidy(@basepath) + @tidy.must be_tidy(@basepath) end it "should tidy a file if age and size are set but only age matches" do @@ -381,7 +381,7 @@ describe tidy do @tidy.parameter(:size).stubs(:tidy?).returns false @tidy.parameter(:age).stubs(:tidy?).returns true - @tidy.should be_tidy(@basepath) + @tidy.must be_tidy(@basepath) end it "should tidy all files if neither age nor size is set" do diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb index bb235b798..290fd6395 100755 --- a/spec/unit/type/user_spec.rb +++ b/spec/unit/type/user_spec.rb @@ -111,11 +111,11 @@ describe Puppet::Type.type(:user) do describe "when managing the ensure property" do it "should support a :present value" do - lambda { described_class.new(:name => 'foo', :ensure => :present) }.should_not raise_error + expect { described_class.new(:name => 'foo', :ensure => :present) }.to_not raise_error end it "should support an :absent value" do - lambda { described_class.new(:name => 'foo', :ensure => :absent) }.should_not raise_error + expect { described_class.new(:name => 'foo', :ensure => :absent) }.to_not raise_error end it "should call :create on the provider when asked to sync to the :present state" do @@ -212,20 +212,20 @@ describe Puppet::Type.type(:user) do describe "when managing groups" do it "should support a singe group" do - lambda { described_class.new(:name => 'foo', :groups => 'bar') }.should_not raise_error + expect { described_class.new(:name => 'foo', :groups => 'bar') }.to_not raise_error end it "should support multiple groups as an array" do - lambda { described_class.new(:name => 'foo', :groups => [ 'bar' ]) }.should_not raise_error - lambda { described_class.new(:name => 'foo', :groups => [ 'bar', 'baz' ]) }.should_not raise_error + expect { described_class.new(:name => 'foo', :groups => [ 'bar' ]) }.to_not raise_error + expect { described_class.new(:name => 'foo', :groups => [ 'bar', 'baz' ]) }.to_not raise_error end it "should not support a comma separated list" do - lambda { described_class.new(:name => 'foo', :groups => 'bar,baz') }.should raise_error(Puppet::Error, /Group names must be provided as an array/) + expect { described_class.new(:name => 'foo', :groups => 'bar,baz') }.to raise_error(Puppet::Error, /Group names must be provided as an array/) end it "should not support an empty string" do - lambda { described_class.new(:name => 'foo', :groups => '') }.should raise_error(Puppet::Error, /Group names must not be empty/) + expect { described_class.new(:name => 'foo', :groups => '') }.to raise_error(Puppet::Error, /Group names must not be empty/) end describe "when testing is in sync" do @@ -262,27 +262,27 @@ describe Puppet::Type.type(:user) do describe "when managing expiry" do it "should fail if given an invalid date" do - lambda { described_class.new(:name => 'foo', :expiry => "200-20-20") }.should raise_error(Puppet::Error, /Expiry dates must be YYYY-MM-DD/) + expect { described_class.new(:name => 'foo', :expiry => "200-20-20") }.to raise_error(Puppet::Error, /Expiry dates must be YYYY-MM-DD/) end end describe "when managing minimum password age" do it "should accept a negative minimum age" do - expect { described_class.new(:name => 'foo', :password_min_age => '-1') }.should_not raise_error + expect { described_class.new(:name => 'foo', :password_min_age => '-1') }.to_not raise_error end it "should fail with an empty minimum age" do - expect { described_class.new(:name => 'foo', :password_min_age => '') }.should raise_error(Puppet::Error, /minimum age must be provided as a number/) + expect { described_class.new(:name => 'foo', :password_min_age => '') }.to raise_error(Puppet::Error, /minimum age must be provided as a number/) end end describe "when managing maximum password age" do it "should accept a negative maximum age" do - expect { described_class.new(:name => 'foo', :password_max_age => '-1') }.should_not raise_error + expect { described_class.new(:name => 'foo', :password_max_age => '-1') }.to_not raise_error end it "should fail with an empty maximum age" do - expect { described_class.new(:name => 'foo', :password_max_age => '') }.should raise_error(Puppet::Error, /maximum age must be provided as a number/) + expect { described_class.new(:name => 'foo', :password_max_age => '') }.to raise_error(Puppet::Error, /maximum age must be provided as a number/) end end @@ -308,17 +308,17 @@ describe Puppet::Type.type(:user) do end it "should fail if a ':' is included in the password" do - lambda { described_class.new(:name => 'foo', :password => "some:thing") }.should raise_error(Puppet::Error, /Passwords cannot include ':'/) + expect { described_class.new(:name => 'foo', :password => "some:thing") }.to raise_error(Puppet::Error, /Passwords cannot include ':'/) end it "should allow the value to be set to :absent" do - lambda { described_class.new(:name => 'foo', :password => :absent) }.should_not raise_error + expect { described_class.new(:name => 'foo', :password => :absent) }.to_not raise_error end end describe "when manages_solaris_rbac is enabled" do it "should support a :role value for ensure" do - lambda { described_class.new(:name => 'foo', :ensure => :role) }.should_not raise_error + expect { described_class.new(:name => 'foo', :ensure => :role) }.to_not raise_error end end diff --git a/spec/unit/type/vlan_spec.rb b/spec/unit/type/vlan_spec.rb index 7d7a0b178..ed6e2ed82 100755 --- a/spec/unit/type/vlan_spec.rb +++ b/spec/unit/type/vlan_spec.rb @@ -12,7 +12,7 @@ describe Puppet::Type.type(:vlan) do end it "should be applied on device" do - Puppet::Type.type(:vlan).new(:name => "200").should be_appliable_to_device + Puppet::Type.type(:vlan).new(:name => "200").must be_appliable_to_device end it "should have an ensure property" do diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb index 1e3f46d9a..57ced3bfb 100755 --- a/spec/unit/type_spec.rb +++ b/spec/unit/type_spec.rb @@ -13,17 +13,17 @@ describe Puppet::Type, :fails_on_windows => true do this.sort.should == [a, b, c] end - a.should be < b - a.should be < c - b.should be > a - b.should be < c - c.should be > a - c.should be > b + a.must be < b + a.must be < c + b.must be > a + b.must be < c + c.must be > a + c.must be > b - [a, b, c].each {|x| a.should be <= x } - [a, b, c].each {|x| c.should be >= x } + [a, b, c].each {|x| a.must be <= x } + [a, b, c].each {|x| c.must be >= x } - b.should be_between(a, c) + b.must be_between(a, c) end it "should consider a parameter to be valid if it is a valid parameter" do @@ -63,7 +63,7 @@ describe Puppet::Type, :fails_on_windows => true do end it "should have a method for setting default values for resources" do - Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:set_default) + Puppet::Type.type(:mount).new(:name => "foo").must respond_to(:set_default) end it "should do nothing for attributes that have no defaults and no specified value" do @@ -71,7 +71,7 @@ describe Puppet::Type, :fails_on_windows => true do end it "should have a method for adding tags" do - Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:tags) + Puppet::Type.type(:mount).new(:name => "foo").must respond_to(:tags) end it "should use the tagging module" do @@ -97,11 +97,11 @@ describe Puppet::Type, :fails_on_windows => true do end it "should have a method to know if the resource is exported" do - Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:exported?) + Puppet::Type.type(:mount).new(:name => "foo").must respond_to(:exported?) end it "should have a method to know if the resource is virtual" do - Puppet::Type.type(:mount).new(:name => "foo").should respond_to(:virtual?) + Puppet::Type.type(:mount).new(:name => "foo").must respond_to(:virtual?) end it "should consider its version to be its catalog version" do @@ -286,7 +286,7 @@ describe Puppet::Type, :fails_on_windows => true do describe "and passed a TransObject" do it "should fail" do trans = Puppet::TransObject.new("/foo", :mount) - lambda { Puppet::Type.type(:mount).new(trans) }.should raise_error(Puppet::DevError) + expect { Puppet::Type.type(:mount).new(trans) }.to raise_error(Puppet::DevError) end end @@ -362,7 +362,7 @@ describe Puppet::Type, :fails_on_windows => true do end it "should fail if any invalid attributes have been provided" do - lambda { Puppet::Type.type(:mount).new(:title => "/foo", :nosuchattr => "whatever") }.should raise_error(Puppet::Error) + expect { Puppet::Type.type(:mount).new(:title => "/foo", :nosuchattr => "whatever") }.to raise_error(Puppet::Error) end it "should set its name to the resource's title if the resource does not have a :name or namevar parameter set" do @@ -372,7 +372,7 @@ describe Puppet::Type, :fails_on_windows => true do end it "should fail if no title, name, or namevar are provided" do - lambda { Puppet::Type.type(:file).new(:atboot => true) }.should raise_error(Puppet::Error) + expect { Puppet::Type.type(:file).new(:atboot => true) }.to raise_error(Puppet::Error) end it "should set the attributes in the order returned by the class's :allattrs method" do @@ -485,7 +485,7 @@ describe Puppet::Type, :fails_on_windows => true do it "should fail if its provider is unsuitable" do @resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) @resource.provider.class.expects(:suitable?).returns false - lambda { @resource.retrieve_resource }.should raise_error(Puppet::Error) + expect { @resource.retrieve_resource }.to raise_error(Puppet::Error) end it "should return a Puppet::Resource instance with its type and title set appropriately" do @@ -583,24 +583,21 @@ describe Puppet::Type, :fails_on_windows => true do it "should be suitable if its type doesn't use providers" do type.stubs(:paramclass).with(:provider).returns nil - - resource.should be_suitable + resource.must be_suitable end it "should be suitable if it has a provider which is suitable" do - resource.should be_suitable + resource.must be_suitable end it "should not be suitable if it has a provider which is not suitable" do provider.class.stubs(:suitable?).returns false - resource.should_not be_suitable end it "should be suitable if it does not have a provider and there is a default provider" do resource.stubs(:provider).returns nil - - resource.should be_suitable + resource.must be_suitable end it "should not be suitable if it doesn't have a provider and there is not default provider" do @@ -626,7 +623,7 @@ describe Puppet::Type, :fails_on_windows => true do end end - expect { fake_type.instances }.should_not raise_error + expect { fake_type.instances }.to_not raise_error end end @@ -745,7 +742,7 @@ describe Puppet::Type.metaparamclass(:audit) do end it "should fail if asked to audit an invalid property" do - lambda { @resource[:audit] = :foobar }.should raise_error(Puppet::Error) + expect { @resource[:audit] = :foobar }.to raise_error(Puppet::Error) end it "should create an attribute instance for each auditable property" do diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb index 47ee54e1f..e243b6c18 100755 --- a/spec/unit/util/autoload_spec.rb +++ b/spec/unit/util/autoload_spec.rb @@ -101,23 +101,29 @@ describe Puppet::Util::Autoload do describe "when loading all files" do before do @autoload.stubs(:searchpath).returns %w{/a} - Dir.stubs(:glob).returns "/path/to/file.rb" - - @autoload.class.stubs(:loaded?).returns(false) + @filename = rand(10000).to_s + ".rb" + Dir.stubs(:glob).returns(@filename) end [RuntimeError, LoadError, SyntaxError].each do |error| - it "should die an if a #{error.to_s} exception is thrown", :'fails_on_ruby_1.9.2' => true do + it "dies if a #{error.to_s} exception is thrown", :'fails_on_ruby_1.9.2' => true do Kernel.expects(:require).raises error - lambda { @autoload.loadall }.should raise_error(Puppet::Error) + expect { @autoload.loadall }.to raise_error(Puppet::Error) end end - it "should require the full path to the file", :'fails_on_ruby_1.9.2' => true do - Kernel.expects(:require).with("/path/to/file.rb") + it "requires the file", :'fails_on_ruby_1.9.2' => true do + Kernel.expects(:require).with(@filename) @autoload.loadall end + + it "marks the file as required even if loading fails", :'fails_on_ruby_1.9.2' => true do + Dir.stubs(:glob).returns "/this/file/does/not/exist.rb" + + expect { @autoload.loadall }.to raise_error(Puppet::Error) + expect { @autoload.loadall }.not_to raise_error + end end end diff --git a/spec/unit/util/backups_spec.rb b/spec/unit/util/backups_spec.rb index d2f36a6e6..7e588e204 100755 --- a/spec/unit/util/backups_spec.rb +++ b/spec/unit/util/backups_spec.rb @@ -6,152 +6,121 @@ require 'puppet/util/backups' describe Puppet::Util::Backups do include PuppetSpec::Files - before do - FileTest.stubs(:exists?).returns true - @nosuchfile = make_absolute('/no/such/file') + let(:bucket) { stub('bucket', :name => "foo") } + let!(:file) do + f = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') + f.stubs(:bucket).returns(bucket) + f end describe "when backing up a file" do + let(:path) { make_absolute('/no/such/file') } + it "should noop if the file does not exist" do - FileTest.expects(:exists?).returns false - file = Puppet::Type.type(:file).new(:name => @nosuchfile) + file = Puppet::Type.type(:file).new(:name => path) + file.expects(:bucket).never + FileTest.expects(:exists?).with(path).returns false file.perform_backup end it "should succeed silently if self[:backup] is false" do - file = Puppet::Type.type(:file).new(:name => @nosuchfile, :backup => false) + file = Puppet::Type.type(:file).new(:name => path, :backup => false) + file.expects(:bucket).never FileTest.expects(:exists?).never + file.perform_backup end it "a bucket should be used when provided" do - path = make_absolute('/my/file') - File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) - - file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') - bucket = stub('bucket', 'name' => 'foo') - file.stubs(:bucket).returns bucket - bucket.expects(:backup).with(path).returns("mysum") + FileTest.expects(:exists?).with(path).returns(true) file.perform_backup end it "should propagate any exceptions encountered when backing up to a filebucket" do - path = make_absolute('/my/file') - File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) - - file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') - bucket = stub('bucket', 'name' => 'foo') - file.stubs(:bucket).returns bucket - bucket.expects(:backup).raises ArgumentError + FileTest.expects(:exists?).with(path).returns(true) lambda { file.perform_backup }.should raise_error(ArgumentError) end - describe "and no filebucket is configured" do - it "should remove any local backup if one exists" do - path = make_absolute('/my/file') - FileTest.stubs(:exists?).returns true - - backup = path + ".foo" + describe "and local backup is configured" do + let(:ext) { 'foobkp' } + let(:backup) { path + '.' + ext } + let(:file) { Puppet::Type.type(:file).new(:name => path, :backup => '.'+ext) } + it "should remove any local backup if one exists" do File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file") File.expects(:unlink).with(backup) - FileUtils.stubs(:cp_r) + FileTest.expects(:exists?).with(path).returns(true) - file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup end it "should fail when the old backup can't be removed" do - path = make_absolute('/my/file') - FileTest.stubs(:exists?).returns true - - backup = path + ".foo" - File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file") File.expects(:unlink).raises ArgumentError - FileUtils.expects(:cp_r).never + FileTest.expects(:exists?).with(path).returns(true) - file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') lambda { file.perform_backup }.should raise_error(Puppet::Error) end it "should not try to remove backups that don't exist" do - path = make_absolute('/my/file') - FileTest.stubs(:exists?).returns true - - backup = path + ".foo" - File.expects(:lstat).with(backup).raises(Errno::ENOENT) File.expects(:unlink).never - FileUtils.stubs(:cp_r) + FileTest.expects(:exists?).with(path).returns(true) - file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup end it "a copy should be created in the local directory" do - path = make_absolute('/my/file') - FileTest.stubs(:exists?).with(path).returns true + FileUtils.expects(:cp_r).with(path, backup, :preserve => true) + FileTest.stubs(:exists?).with(path).returns(true) - FileUtils.expects(:cp_r).with(path, path + ".foo", :preserve => true) - - file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup.should be_true end it "should propagate exceptions if no backup can be created" do - path = make_absolute('/my/file') - FileTest.stubs(:exists?).with(path).returns true - FileUtils.expects(:cp_r).raises ArgumentError - file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') + FileTest.stubs(:exists?).with(path).returns(true) lambda { file.perform_backup }.should raise_error(Puppet::Error) end end end describe "when backing up a directory" do - it "a bucket should work when provided" do - path = make_absolute('/my/dir') - - File.stubs(:file?).returns true - Find.expects(:find).with(path).yields(make_absolute("/my/dir/file")) + let(:path) { make_absolute('/my/dir') } + let(:filename) { File.join(path, 'file') } - bucket = stub('bucket', :name => "eh") - bucket.expects(:backup).with(make_absolute("/my/dir/file")).returns true + it "a bucket should work when provided" do + File.stubs(:file?).with(filename).returns true + Find.expects(:find).with(path).yields(filename) - file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') - file.stubs(:bucket).returns bucket + bucket.expects(:backup).with(filename).returns true File.stubs(:stat).with(path).returns(stub('stat', :ftype => 'directory')) + FileTest.stubs(:exists?).with(path).returns(true) + FileTest.stubs(:exists?).with(filename).returns(true) + file.perform_backup end it "should do nothing when recursing" do - path = make_absolute('/my/dir') - - bucket = stub('bucket', :name => "eh") - bucket.expects(:backup).never - file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo', :recurse => true) - file.stubs(:bucket).returns bucket + bucket.expects(:backup).never File.stubs(:stat).with(path).returns(stub('stat', :ftype => 'directory')) - Find.expects(:find).never file.perform_backup diff --git a/spec/unit/util/storage_spec.rb b/spec/unit/util/storage_spec.rb index 575ad1ef3..34839d423 100755 --- a/spec/unit/util/storage_spec.rb +++ b/spec/unit/util/storage_spec.rb @@ -183,13 +183,12 @@ describe Puppet::Util::Storage do describe "when storing to the state file" do before(:each) do - @state_file = Tempfile.new('storage_test') + @state_file = tmpfile('storage_test') @saved_statefile = Puppet[:statefile] - Puppet[:statefile] = @state_file.path + Puppet[:statefile] = @state_file end it "should create the state file if it does not exist" do - @state_file.close!() FileTest.exists?(Puppet[:statefile]).should be_false Puppet::Util::Storage.cache(:yayness) @@ -198,7 +197,6 @@ describe Puppet::Util::Storage do end it "should raise an exception if the state file is not a regular file" do - @state_file.close!() Dir.mkdir(Puppet[:statefile]) Puppet::Util::Storage.cache(:yayness) @@ -224,10 +222,5 @@ describe Puppet::Util::Storage do proc { Puppet::Util::Storage.load }.should_not raise_error Puppet::Util::Storage.state.should == {:yayness=>{}} end - - after(:each) do - @state_file.close!() - Puppet[:statefile] = @saved_statefile - end end end diff --git a/spec/unit/util/suidmanager_spec.rb b/spec/unit/util/suidmanager_spec.rb index 187754ab6..bcdd37638 100755 --- a/spec/unit/util/suidmanager_spec.rb +++ b/spec/unit/util/suidmanager_spec.rb @@ -278,6 +278,6 @@ describe 'Puppet::Util::SUIDManager#groups=' do it "(#3419) should fail if an Errno::EINVAL is raised NOT on OS X" do Process.expects(:groups=).raises(Errno::EINVAL, 'blew up') subject.expects(:osx_maj_ver).returns(false) - expect { subject.groups = ['list', 'of', 'groups'] }.should raise_error(Errno::EINVAL) + expect { subject.groups = ['list', 'of', 'groups'] }.to raise_error(Errno::EINVAL) end end diff --git a/spec/unit/util_spec.rb b/spec/unit/util_spec.rb index 5cc762802..af6797b6f 100755 --- a/spec/unit/util_spec.rb +++ b/spec/unit/util_spec.rb @@ -411,7 +411,7 @@ describe Puppet::Util do end it "should wait for the child process to exit" do - Puppet::Util.stubs(:wait_for_output) + Puppet::Util.expects(:wait_for_output) Puppet::Util.execute('test command') end @@ -456,6 +456,16 @@ describe Puppet::Util do File.should_not be_exist(path) end + it "should not raise an error if the file is open" do + stdout = Tempfile.new('test') + Tempfile.stubs(:new).returns(stdout) + file = File.new(stdout.path, 'r') + + expect { + Puppet::Util.execute('test command') + }.to_not raise_error + end + it "should raise an error if failonfail is true and the child failed" do stub_process_wait(1) @@ -709,20 +719,12 @@ describe Puppet::Util do expect { subject.replace_file(target.path, 0600) }.to raise_error /block/ end - it "should replace a file when invoked" do - # Check that our file has the expected content. - File.read(target.path).should == "hello, world\n" - - # Replace the file. - subject.replace_file(target.path, 0600) do |fh| - fh.puts "I am the passenger..." - end - - # ...and check the replacement was complete. - File.read(target.path).should == "I am the passenger...\n" - end - - [0555, 0600, 0660, 0700, 0770].each do |mode| + # When running with the same user and group sid, which is the default, + # Windows collapses the owner and group modes into a single ACE, resulting + # in set(0600) => get(0660) and so forth. --daniel 2012-03-30 + modes = [0555, 0660, 0770] + modes += [0600, 0700] unless Puppet.features.microsoft_windows? + modes.each do |mode| it "should copy 0#{mode.to_s(8)} permissions from the target file by default" do set_mode(mode, target.path) @@ -735,9 +737,9 @@ describe Puppet::Util do end end - it "should copy the permissions of the source file before yielding" do + it "should copy the permissions of the source file before yielding on Unix", :if => !Puppet.features.microsoft_windows? do set_mode(0555, target.path) - inode = File.stat(target.path).ino unless Puppet.features.microsoft_windows? + inode = File.stat(target.path).ino yielded = false subject.replace_file(target.path, 0600) do |fh| @@ -746,9 +748,7 @@ describe Puppet::Util do end yielded.should be_true - # We can't check inode on Windows - File.stat(target.path).ino.should_not == inode unless Puppet.features.microsoft_windows? - + File.stat(target.path).ino.should_not == inode get_mode(target.path).should == 0555 end @@ -789,13 +789,5 @@ describe Puppet::Util do File.read(target.path).should == "hello, world\n" end end - - describe "on Windows platforms" do - it "should fail and complain" do - Puppet.features.stubs(:microsoft_windows?).returns true - - expect { Puppet::Util.replace_file("C:/foo", 0644) {} }.to raise_error(Puppet::DevError, "replace_file is non-functional on Windows") - end - end end end diff --git a/test/ral/manager/attributes.rb b/test/ral/manager/attributes.rb index 8b0b8df95..c3e449e9e 100755 --- a/test/ral/manager/attributes.rb +++ b/test/ral/manager/attributes.rb @@ -227,7 +227,7 @@ class TestTypeAttributes < Test::Unit::TestCase no.each do |a| assert_nil(resource.should(a), "Got value for unsupported %s in %s" % [a, prov.name]) if Puppet::Util::Log.sendlevel?(:info) - assert(@logs.find { |l| l.message =~ /not managing attribute #{a}/ and l.level == :info }, "No warning about failed %s" % a) + assert(@logs.find { |l| l.message =~ /not managing attribute #{a}/ and l.level == :debug }, "No warning about failed %s" % a) end end |
