diff options
| author | Stig Sandbeck Mathisen <ssm@debian.org> | 2013-09-18 20:32:48 +0200 |
|---|---|---|
| committer | Stig Sandbeck Mathisen <ssm@debian.org> | 2013-09-18 20:32:48 +0200 |
| commit | 0058e988d41e0a2d05e6df6a473b18536fa30d59 (patch) | |
| tree | fe9845888d3a765cbe18a5a9c81ec805243a63f3 | |
| parent | be7c52988cc33b0a4c3c3f7648b8f591c9db996d (diff) | |
| parent | 2471c0fc83ed394db052cac242f6b90d0df07289 (diff) | |
| download | puppet-upstream/2.7.23.tar.gz | |
Imported Upstream version 2.7.23upstream/2.7.23
99 files changed, 4755 insertions, 1582 deletions
@@ -1,3 +1,38 @@ +2.7.23 +=== +4295e3d (maint) Fix module_utils regex tests for module file perms +a322f34 (Maint) Update test to reflect chown using the gid too +28bda0f (Maint) Update expectations for older rspec +be2d182 Improving testing around PMT module install permissions. +7114934 Ensure that PMT uses the correct group membership. +64d2637 (#21971) Allow paths that contain .. as part of a name +d88dd3f (Maint) Confine module tool tests off of windows +9e5ef53 Fixing broken requires in the acceptance tests. +878c420 (#21971) Fixes PathPattern's usage of Dir.glob for Windows +2455fac (#21971) Fix how import_all loads files +7a13291 (#21971) Create system for safely dealing with path patterns +3c8dc4a (#21971) Split import and autoloading code paths +0a35ef4 (#21971) Check for possible directory traversal +30a72ce (Maint) Clean up specs +c3d1703 (Maint) Use dirname instead of regexes +f02f186 Backporting acceptance tests. +90d4180 (#14333) Ensure module permissions are sane. + + +2.7.22 +=== +ba8c021 [packaging] Update mocks for rpmbuilder mock format +7f40007 (packaging) Update debian build-depends to be ruby1.8 so that the shebang is correct after install and ruby1.9.1 isn't used on newer debians. +96be982 (packaging) Update build_defaults to remove EOL platforms (natty, f15, f16). +fea3cb6 Improve CVE 2013 1654 SSLv2 Downgrade Master test +fd758ad Remove acceptance test for yaml parsing that was no longer valid +5926d1a (#20584) Only deserialize expected objects from YAML +e8c30cb Vendor safe_yaml 0.9.2 +ee741eb Fix installation of vendored libs +2333fa4 Add vendoring system into puppet +535da9b Add acceptance test for report processing +788fdaf Don't keep Gemfile.lock checked in. + 2.7.21 === 570e4d2 Update CHANGELOG, PUPPETVERSION for 2.7.21 diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index e457e0926..000000000 --- a/Gemfile.lock +++ /dev/null @@ -1,44 +0,0 @@ -PATH - remote: . - specs: - puppet (2.7.19) - facter (~> 1.5) - -GEM - remote: http://rubygems.org/ - specs: - diff-lcs (1.1.3) - facter (1.6.11) - metaclass (0.0.1) - mocha (0.10.5) - metaclass (~> 0.0.1) - rack (1.4.1) - rspec (2.10.0) - rspec-core (~> 2.10.0) - rspec-expectations (~> 2.10.0) - rspec-mocks (~> 2.10.0) - rspec-core (2.10.1) - rspec-expectations (2.10.0) - diff-lcs (~> 1.1.3) - rspec-mocks (2.10.1) - -PLATFORMS - ruby - -DEPENDENCIES - facter (~> 1.6.4) - mocha (~> 0.10.5) - puppet! - rack (~> 1.4.1) - rspec (~> 2.10.0) - sys-admin (~> 1.5.6) - win32-api (~> 1.4.8) - win32-dir (~> 0.3.7) - win32-eventlog (~> 0.5.3) - win32-process (~> 0.6.5) - win32-security (~> 0.1.4) - win32-service (~> 0.7.2) - win32-taskscheduler (~> 0.2.2) - win32console (~> 1.3.2) - windows-api (~> 0.4.1) - windows-pr (~> 1.2.1) @@ -9,8 +9,6 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), 'tasks') begin require 'rubygems' require 'rubygems/package_task' - require 'rspec' - require 'rspec/core/rake_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 diff --git a/ext/build_defaults.yaml b/ext/build_defaults.yaml index cce7f889e..1c84d1dd2 100644 --- a/ext/build_defaults.yaml +++ b/ext/build_defaults.yaml @@ -2,15 +2,14 @@ packaging_url: 'git://github.com/puppetlabs/packaging.git --branch=master' packaging_repo: 'packaging' default_cow: 'base-squeeze-i386.cow' -cows: 'base-lucid-i386.cow base-natty-i386.cow base-oneiric-i386.cow base-precise-i386.cow base-quantal-i386.cow base-sid-i386.cow base-squeeze-i386.cow base-stable-i386.cow base-testing-i386.cow base-unstable-i386.cow base-wheezy-i386.cow' +cows: 'base-lucid-i386.cow base-precise-i386.cow base-quantal-i386.cow base-sid-i386.cow base-squeeze-i386.cow base-stable-i386.cow base-testing-i386.cow base-unstable-i386.cow base-wheezy-i386.cow' pbuild_conf: '/etc/pbuilderrc' packager: 'puppetlabs' gpg_name: 'info@puppetlabs.com' gpg_key: '4BD6EC30' sign_tar: False # a space separated list of mock configs -final_mocks: 'pl-5-i386 pl-6-i386 fedora-15-i386 fedora-16-i386 fedora-17-i386' -rc_mocks: 'pl-5-i386-dev pl-6-i386-dev fedora-15-i386-dev fedora-16-i386-dev fedora-17-i386-dev' +final_mocks: 'pl-el-5-i386 pl-el-6-i386 pl-fedora-17-i386' yum_host: 'burji.puppetlabs.com' yum_repo_path: '/opt/repository/yum/' build_gem: FALSE diff --git a/ext/debian/changelog b/ext/debian/changelog index eadcc9c04..c812ec179 100644 --- a/ext/debian/changelog +++ b/ext/debian/changelog @@ -1,8 +1,8 @@ -puppet (2.7.21-1puppetlabs1) hardy lucid natty oneiric unstable sid squeeze wheezy precise; urgency=low +puppet (2.7.23-1puppetlabs1) hardy lucid natty oneiric unstable sid squeeze wheezy precise; urgency=low - * Update to version 2.7.21-1puppetlabs1 + * Update to version 2.7.23-1puppetlabs1 - -- Puppet Labs Release <info@puppetlabs.com> Mon, 11 Mar 2013 10:35:11 -0700 + -- Puppet Labs Release <info@puppetlabs.com> Wed, 14 Aug 2013 14:40:35 -0700 puppet (2.7.19-1puppetlabs2) hardy jaunty karmic lucid maverick natty oneiric unstable lenny sid squeeze wheezy precise; urgency=low diff --git a/ext/debian/control b/ext/debian/control index c281a4f6c..cbc2ce68b 100644 --- a/ext/debian/control +++ b/ext/debian/control @@ -3,7 +3,7 @@ Section: admin Priority: optional Maintainer: Puppet Labs <info@puppetlabs.com> Uploaders: Micah Anderson <micah@debian.org>, Andrew Pollock <apollock@debian.org>, Nigel Kersten <nigel@explanatorygap.net>, Stig Sandbeck Mathisen <ssm@debian.org> -Build-Depends-Indep: ruby (>= 1.8.1), libopenssl-ruby, facter (>= 1.5), facter (<< 2.0) +Build-Depends-Indep: ruby1.8, libopenssl-ruby, facter (>= 1.5), facter (<< 2.0) Build-Depends: debhelper (>= 7.0.0), openssl Standards-Version: 3.9.1 Vcs-Git: git://git.debian.org/git/pkg-puppet/puppet.git diff --git a/ext/osx/preflight b/ext/osx/preflight index c5ab117da..9422f53af 100644 --- a/ext/osx/preflight +++ b/ext/osx/preflight @@ -15,1502 +15,1594 @@ -/bin/rm -Rf "${3}/puppet.rb" +/bin/rm -Rf "${3}/semver.rb" -/bin/rm -Rf "${3}/puppet/agent.rb" +/bin/rm -Rf "${3}/puppet/face/ca.rb" -/bin/rm -Rf "${3}/puppet/module_tool/contents_description.rb" +/bin/rm -Rf "${3}/puppet/face/certificate_revocation_list.rb" -/bin/rm -Rf "${3}/puppet/module_tool/checksums.rb" +/bin/rm -Rf "${3}/puppet/face/resource.rb" -/bin/rm -Rf "${3}/puppet/module_tool/shared_behaviors.rb" +/bin/rm -Rf "${3}/puppet/face/module.rb" -/bin/rm -Rf "${3}/puppet/module_tool/dependency.rb" +/bin/rm -Rf "${3}/puppet/face/plugin.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors/shared.rb" +/bin/rm -Rf "${3}/puppet/face/config.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors/uninstaller.rb" +/bin/rm -Rf "${3}/puppet/face/status.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors/base.rb" +/bin/rm -Rf "${3}/puppet/face/certificate_request.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors/installer.rb" +/bin/rm -Rf "${3}/puppet/face/catalog/select.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors/upgrader.rb" +/bin/rm -Rf "${3}/puppet/face/man.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/uninstaller.rb" +/bin/rm -Rf "${3}/puppet/face/file/download.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/installer.rb" +/bin/rm -Rf "${3}/puppet/face/file/store.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/checksummer.rb" +/bin/rm -Rf "${3}/puppet/face/certificate.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/upgrader.rb" +/bin/rm -Rf "${3}/puppet/face/instrumentation_listener.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/application.rb" +/bin/rm -Rf "${3}/puppet/face/node/clean.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/searcher.rb" +/bin/rm -Rf "${3}/puppet/face/file.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/generator.rb" +/bin/rm -Rf "${3}/puppet/face/help.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/builder.rb" +/bin/rm -Rf "${3}/puppet/face/parser.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications/unpacker.rb" +/bin/rm -Rf "${3}/puppet/face/instrumentation_probe.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb" +/bin/rm -Rf "${3}/puppet/face/secret_agent.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/tests/init.pp.erb" +/bin/rm -Rf "${3}/puppet/face/resource_type.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/Modulefile.erb" +/bin/rm -Rf "${3}/puppet/face/node.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/README.erb" +/bin/rm -Rf "${3}/puppet/face/facts.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/spec/spec_helper.rb" +/bin/rm -Rf "${3}/puppet/face/module/search.rb" -/bin/rm -Rf "${3}/puppet/module_tool/applications.rb" +/bin/rm -Rf "${3}/puppet/face/module/build.rb" -/bin/rm -Rf "${3}/puppet/module_tool/metadata.rb" +/bin/rm -Rf "${3}/puppet/face/module/list.rb" -/bin/rm -Rf "${3}/puppet/module_tool/skeleton.rb" +/bin/rm -Rf "${3}/puppet/face/module/uninstall.rb" -/bin/rm -Rf "${3}/puppet/module_tool/modulefile.rb" +/bin/rm -Rf "${3}/puppet/face/module/upgrade.rb" -/bin/rm -Rf "${3}/puppet/module_tool/errors.rb" +/bin/rm -Rf "${3}/puppet/face/module/changes.rb" -/bin/rm -Rf "${3}/puppet/parser/ast.rb" +/bin/rm -Rf "${3}/puppet/face/module/generate.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/comparison_operator.rb" +/bin/rm -Rf "${3}/puppet/face/module/install.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/definition.rb" +/bin/rm -Rf "${3}/puppet/face/report.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/astarray.rb" +/bin/rm -Rf "${3}/puppet/face/catalog.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/in_operator.rb" +/bin/rm -Rf "${3}/puppet/face/instrumentation_data.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/minus.rb" +/bin/rm -Rf "${3}/puppet/face/help/man.erb" -/bin/rm -Rf "${3}/puppet/parser/ast/resourceparam.rb" +/bin/rm -Rf "${3}/puppet/face/help/action.erb" -/bin/rm -Rf "${3}/puppet/parser/ast/collexpr.rb" +/bin/rm -Rf "${3}/puppet/face/help/face.erb" -/bin/rm -Rf "${3}/puppet/parser/ast/not.rb" +/bin/rm -Rf "${3}/puppet/face/help/global.erb" -/bin/rm -Rf "${3}/puppet/parser/ast/boolean_operator.rb" +/bin/rm -Rf "${3}/puppet/face/key.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/function.rb" +/bin/rm -Rf "${3}/puppet/application.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/node.rb" +/bin/rm -Rf "${3}/puppet/configurer.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/resource.rb" +/bin/rm -Rf "${3}/puppet/relationship.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/tag.rb" +/bin/rm -Rf "${3}/puppet/resource.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/relationship.rb" +/bin/rm -Rf "${3}/puppet/module.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/casestatement.rb" +/bin/rm -Rf "${3}/puppet/module_tool.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/branch.rb" +/bin/rm -Rf "${3}/puppet/status.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/vardef.rb" +/bin/rm -Rf "${3}/puppet/defaults.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/resource_reference.rb" +/bin/rm -Rf "${3}/puppet/reports/rrdgraph.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/leaf.rb" +/bin/rm -Rf "${3}/puppet/reports/store.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/hostclass.rb" +/bin/rm -Rf "${3}/puppet/reports/log.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/nop.rb" +/bin/rm -Rf "${3}/puppet/reports/tagmail.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/arithmetic_operator.rb" +/bin/rm -Rf "${3}/puppet/reports/http.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/top_level_construct.rb" +/bin/rm -Rf "${3}/puppet/provider/zpool/solaris.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/selector.rb" +/bin/rm -Rf "${3}/puppet/provider/vlan/cisco.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/resource_override.rb" +/bin/rm -Rf "${3}/puppet/provider/zfs/solaris.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/match_operator.rb" +/bin/rm -Rf "${3}/puppet/provider/service/debian.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/resource_instance.rb" +/bin/rm -Rf "${3}/puppet/provider/service/service.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/asthash.rb" +/bin/rm -Rf "${3}/puppet/provider/service/systemd.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/collection.rb" +/bin/rm -Rf "${3}/puppet/provider/service/openrc.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/ifstatement.rb" +/bin/rm -Rf "${3}/puppet/provider/service/gentoo.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/resource_defaults.rb" +/bin/rm -Rf "${3}/puppet/provider/service/daemontools.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/caseopt.rb" +/bin/rm -Rf "${3}/puppet/provider/service/launchd.rb" -/bin/rm -Rf "${3}/puppet/parser/ast/else.rb" +/bin/rm -Rf "${3}/puppet/provider/service/init.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/include.rb" +/bin/rm -Rf "${3}/puppet/provider/service/base.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/md5.rb" +/bin/rm -Rf "${3}/puppet/provider/service/redhat.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/require.rb" +/bin/rm -Rf "${3}/puppet/provider/service/freebsd.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/search.rb" +/bin/rm -Rf "${3}/puppet/provider/service/runit.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/defined.rb" +/bin/rm -Rf "${3}/puppet/provider/service/smf.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/tag.rb" +/bin/rm -Rf "${3}/puppet/provider/service/src.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/extlookup.rb" +/bin/rm -Rf "${3}/puppet/provider/service/windows.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/versioncmp.rb" +/bin/rm -Rf "${3}/puppet/provider/service/bsd.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/file.rb" +/bin/rm -Rf "${3}/puppet/provider/service/upstart.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/regsubst.rb" +/bin/rm -Rf "${3}/puppet/provider/maillist/mailman.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/create_resources.rb" +/bin/rm -Rf "${3}/puppet/provider/exec/shell.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/inline_template.rb" +/bin/rm -Rf "${3}/puppet/provider/exec/posix.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/fail.rb" +/bin/rm -Rf "${3}/puppet/provider/exec/windows.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/sha1.rb" +/bin/rm -Rf "${3}/puppet/provider/group/aix.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/realize.rb" +/bin/rm -Rf "${3}/puppet/provider/group/ldap.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/split.rb" +/bin/rm -Rf "${3}/puppet/provider/group/directoryservice.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/sprintf.rb" +/bin/rm -Rf "${3}/puppet/provider/group/groupadd.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/tagged.rb" +/bin/rm -Rf "${3}/puppet/provider/group/windows_adsi.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/shellquote.rb" +/bin/rm -Rf "${3}/puppet/provider/group/pw.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/fqdn_rand.rb" +/bin/rm -Rf "${3}/puppet/provider/parsedfile.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/generate.rb" +/bin/rm -Rf "${3}/puppet/provider/exec.rb" -/bin/rm -Rf "${3}/puppet/parser/functions/template.rb" +/bin/rm -Rf "${3}/puppet/provider/package/hpux.rb" -/bin/rm -Rf "${3}/puppet/parser/parser_support.rb" +/bin/rm -Rf "${3}/puppet/provider/package/msi.rb" -/bin/rm -Rf "${3}/puppet/parser/templatewrapper.rb" +/bin/rm -Rf "${3}/puppet/provider/package/up2date.rb" -/bin/rm -Rf "${3}/puppet/parser/resource.rb" +/bin/rm -Rf "${3}/puppet/provider/package/fink.rb" -/bin/rm -Rf "${3}/puppet/parser/files.rb" +/bin/rm -Rf "${3}/puppet/provider/package/aix.rb" -/bin/rm -Rf "${3}/puppet/parser/relationship.rb" +/bin/rm -Rf "${3}/puppet/provider/package/aptrpm.rb" -/bin/rm -Rf "${3}/puppet/parser/scope.rb" +/bin/rm -Rf "${3}/puppet/provider/package/pkgdmg.rb" -/bin/rm -Rf "${3}/puppet/parser/grammar.ra" +/bin/rm -Rf "${3}/puppet/provider/package/pacman.rb" -/bin/rm -Rf "${3}/puppet/parser/functions.rb" +/bin/rm -Rf "${3}/puppet/provider/package/aptitude.rb" -/bin/rm -Rf "${3}/puppet/parser/lexer.rb" +/bin/rm -Rf "${3}/puppet/provider/package/pkgutil.rb" -/bin/rm -Rf "${3}/puppet/parser/collector.rb" +/bin/rm -Rf "${3}/puppet/provider/package/pkg.rb" -/bin/rm -Rf "${3}/puppet/parser/parser.rb" +/bin/rm -Rf "${3}/puppet/provider/package/blastwave.rb" -/bin/rm -Rf "${3}/puppet/parser/type_loader.rb" +/bin/rm -Rf "${3}/puppet/provider/package/sun.rb" -/bin/rm -Rf "${3}/puppet/parser/makefile" +/bin/rm -Rf "${3}/puppet/provider/package/zypper.rb" -/bin/rm -Rf "${3}/puppet/parser/compiler.rb" +/bin/rm -Rf "${3}/puppet/provider/package/ports.rb" -/bin/rm -Rf "${3}/puppet/parser/resource/param.rb" +/bin/rm -Rf "${3}/puppet/provider/package/gem.rb" -/bin/rm -Rf "${3}/puppet/parser/yaml_trimmer.rb" +/bin/rm -Rf "${3}/puppet/provider/package/yumhelper.py" -/bin/rm -Rf "${3}/puppet/face.rb" +/bin/rm -Rf "${3}/puppet/provider/package/pip.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate_factory.rb" +/bin/rm -Rf "${3}/puppet/provider/package/macports.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate_authority/interface.rb" +/bin/rm -Rf "${3}/puppet/provider/package/portupgrade.rb" -/bin/rm -Rf "${3}/puppet/ssl/base.rb" +/bin/rm -Rf "${3}/puppet/provider/package/rpm.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate_request.rb" +/bin/rm -Rf "${3}/puppet/provider/package/portage.rb" -/bin/rm -Rf "${3}/puppet/ssl/inventory.rb" +/bin/rm -Rf "${3}/puppet/provider/package/urpmi.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate_authority.rb" +/bin/rm -Rf "${3}/puppet/provider/package/freebsd.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate.rb" +/bin/rm -Rf "${3}/puppet/provider/package/openbsd.rb" -/bin/rm -Rf "${3}/puppet/ssl/key.rb" +/bin/rm -Rf "${3}/puppet/provider/package/yum.rb" -/bin/rm -Rf "${3}/puppet/ssl/host.rb" +/bin/rm -Rf "${3}/puppet/provider/package/nim.rb" -/bin/rm -Rf "${3}/puppet/ssl/certificate_revocation_list.rb" +/bin/rm -Rf "${3}/puppet/provider/package/appdmg.rb" -/bin/rm -Rf "${3}/puppet/defaults.rb" +/bin/rm -Rf "${3}/puppet/provider/package/dpkg.rb" -/bin/rm -Rf "${3}/puppet/version.rb" +/bin/rm -Rf "${3}/puppet/provider/package/apt.rb" -/bin/rm -Rf "${3}/puppet/reports.rb" +/bin/rm -Rf "${3}/puppet/provider/package/sunfreeware.rb" -/bin/rm -Rf "${3}/puppet/forge.rb" +/bin/rm -Rf "${3}/puppet/provider/package/apple.rb" -/bin/rm -Rf "${3}/puppet/error.rb" +/bin/rm -Rf "${3}/puppet/provider/package/rug.rb" -/bin/rm -Rf "${3}/puppet/run.rb" +/bin/rm -Rf "${3}/puppet/provider/scheduled_task/win32_taskscheduler.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_server.rb" +/bin/rm -Rf "${3}/puppet/provider/file/posix.rb" -/bin/rm -Rf "${3}/puppet/indirector/face.rb" +/bin/rm -Rf "${3}/puppet/provider/file/windows.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_status/file.rb" +/bin/rm -Rf "${3}/puppet/provider/ldap.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_status/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/user/hpux.rb" -/bin/rm -Rf "${3}/puppet/indirector/terminus.rb" +/bin/rm -Rf "${3}/puppet/provider/user/aix.rb" -/bin/rm -Rf "${3}/puppet/indirector/code.rb" +/bin/rm -Rf "${3}/puppet/provider/user/ldap.rb" -/bin/rm -Rf "${3}/puppet/indirector/ldap.rb" +/bin/rm -Rf "${3}/puppet/provider/user/directoryservice.rb" -/bin/rm -Rf "${3}/puppet/indirector/active_record.rb" +/bin/rm -Rf "${3}/puppet/provider/user/useradd.rb" -/bin/rm -Rf "${3}/puppet/indirector/ssl_file.rb" +/bin/rm -Rf "${3}/puppet/provider/user/windows_adsi.rb" -/bin/rm -Rf "${3}/puppet/indirector/exec.rb" +/bin/rm -Rf "${3}/puppet/provider/user/pw.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/inventory_active_record.rb" +/bin/rm -Rf "${3}/puppet/provider/user/user_role_add.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/active_record.rb" +/bin/rm -Rf "${3}/puppet/provider/network_device.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/couch.rb" +/bin/rm -Rf "${3}/puppet/provider/cisco.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/store_configs.rb" +/bin/rm -Rf "${3}/puppet/provider/naginator.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/yaml.rb" +/bin/rm -Rf "${3}/puppet/provider/mount.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/network_device.rb" +/bin/rm -Rf "${3}/puppet/provider/confine.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/confine_collection.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/facter.rb" +/bin/rm -Rf "${3}/puppet/provider/port/parsed.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/inventory_service.rb" +/bin/rm -Rf "${3}/puppet/provider/mcx/mcxcontent.rb" -/bin/rm -Rf "${3}/puppet/indirector/facts/memory.rb" +/bin/rm -Rf "${3}/puppet/provider/zone/solaris.rb" -/bin/rm -Rf "${3}/puppet/indirector/envelope.rb" +/bin/rm -Rf "${3}/puppet/provider/interface/cisco.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener.rb" +/bin/rm -Rf "${3}/puppet/provider/interface/base.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/file.rb" +/bin/rm -Rf "${3}/puppet/provider/computer/computer.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/aixobject.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/selector.rb" +/bin/rm -Rf "${3}/puppet/provider/selmodule/semodule.rb" -/bin/rm -Rf "${3}/puppet/indirector/status/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/confiner.rb" -/bin/rm -Rf "${3}/puppet/indirector/status/local.rb" +/bin/rm -Rf "${3}/puppet/provider/mailalias/aliases.rb" -/bin/rm -Rf "${3}/puppet/indirector/couch.rb" +/bin/rm -Rf "${3}/puppet/provider/cron/crontab.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/file.rb" +/bin/rm -Rf "${3}/puppet/provider/sshkey/parsed.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/ca.rb" +/bin/rm -Rf "${3}/puppet/provider/nameservice.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/confine/variable.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/disabled_ca.rb" +/bin/rm -Rf "${3}/puppet/provider/confine/false.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate/file.rb" +/bin/rm -Rf "${3}/puppet/provider/confine/feature.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate/ca.rb" +/bin/rm -Rf "${3}/puppet/provider/confine/exists.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/confine/true.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate/disabled_ca.rb" +/bin/rm -Rf "${3}/puppet/provider/selboolean/getsetsebool.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_request/file.rb" +/bin/rm -Rf "${3}/puppet/provider/host/parsed.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_request/ca.rb" +/bin/rm -Rf "${3}/puppet/provider/augeas/augeas.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_request/rest.rb" +/bin/rm -Rf "${3}/puppet/provider/macauthorization/macauthorization.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_request/disabled_ca.rb" +/bin/rm -Rf "${3}/puppet/provider/nameservice/objectadd.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_metadata.rb" +/bin/rm -Rf "${3}/puppet/provider/nameservice/directoryservice.rb" -/bin/rm -Rf "${3}/puppet/indirector/store_configs.rb" +/bin/rm -Rf "${3}/puppet/provider/nameservice/pw.rb" -/bin/rm -Rf "${3}/puppet/indirector/direct_file_server.rb" +/bin/rm -Rf "${3}/puppet/provider/mount/parsed.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/active_record.rb" +/bin/rm -Rf "${3}/puppet/provider/ssh_authorized_key/parsed.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/static_compiler.rb" +/bin/rm -Rf "${3}/puppet/provider/package.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/store_configs.rb" +/bin/rm -Rf "${3}/puppet/resource/status.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/yaml.rb" +/bin/rm -Rf "${3}/puppet/resource/type.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/queue.rb" +/bin/rm -Rf "${3}/puppet/resource/type_collection.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/rest.rb" +/bin/rm -Rf "${3}/puppet/resource/type_collection_helper.rb" -/bin/rm -Rf "${3}/puppet/indirector/catalog/compiler.rb" +/bin/rm -Rf "${3}/puppet/resource/catalog.rb" -/bin/rm -Rf "${3}/puppet/indirector/request.rb" +/bin/rm -Rf "${3}/puppet/util.rb" -/bin/rm -Rf "${3}/puppet/indirector/yaml.rb" +/bin/rm -Rf "${3}/puppet/feature/zlib.rb" -/bin/rm -Rf "${3}/puppet/indirector/indirection.rb" +/bin/rm -Rf "${3}/puppet/feature/stomp.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data/rest.rb" +/bin/rm -Rf "${3}/puppet/feature/rubygems.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data/local.rb" +/bin/rm -Rf "${3}/puppet/feature/base.rb" -/bin/rm -Rf "${3}/puppet/indirector/key/file.rb" +/bin/rm -Rf "${3}/puppet/feature/pson.rb" -/bin/rm -Rf "${3}/puppet/indirector/key/ca.rb" +/bin/rm -Rf "${3}/puppet/feature/eventlog.rb" -/bin/rm -Rf "${3}/puppet/indirector/key/disabled_ca.rb" +/bin/rm -Rf "${3}/puppet/feature/selinux.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe/rest.rb" +/bin/rm -Rf "${3}/puppet/feature/rails.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe/local.rb" +/bin/rm -Rf "${3}/puppet/feature/rack.rb" -/bin/rm -Rf "${3}/puppet/indirector/inventory/yaml.rb" +/bin/rm -Rf "${3}/puppet/feature/ssh.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_content.rb" +/bin/rm -Rf "${3}/puppet/version.rb" -/bin/rm -Rf "${3}/puppet/indirector/queue.rb" +/bin/rm -Rf "${3}/puppet/transportable.rb" -/bin/rm -Rf "${3}/puppet/indirector/rest.rb" +/bin/rm -Rf "${3}/puppet/agent/locker.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_metadata/file_server.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors/upgrader.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_metadata/file.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors/installer.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_metadata/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors/uninstaller.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_metadata/selector.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors/shared.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors/base.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener/local.rb" +/bin/rm -Rf "${3}/puppet/module_tool/checksums.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_content/file_server.rb" +/bin/rm -Rf "${3}/puppet/module_tool/contents_description.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_content/file.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/spec/spec_helper.rb" -/bin/rm -Rf "${3}/puppet/indirector/file_content/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/tests/init.pp.erb" -/bin/rm -Rf "${3}/puppet/indirector/file_content/selector.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/README.erb" -/bin/rm -Rf "${3}/puppet/indirector/resource_type/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb" -/bin/rm -Rf "${3}/puppet/indirector/resource_type/parser.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton/templates/generator/Modulefile.erb" -/bin/rm -Rf "${3}/puppet/indirector/status.rb" +/bin/rm -Rf "${3}/puppet/module_tool/metadata.rb" -/bin/rm -Rf "${3}/puppet/indirector/plain.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/upgrader.rb" -/bin/rm -Rf "${3}/puppet/indirector/report/processor.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/application.rb" -/bin/rm -Rf "${3}/puppet/indirector/report/yaml.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/searcher.rb" -/bin/rm -Rf "${3}/puppet/indirector/report/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/installer.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/uninstaller.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource/active_record.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/generator.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource/ral.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/builder.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource/store_configs.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/unpacker.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource/rest.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications/checksummer.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource/validator.rb" +/bin/rm -Rf "${3}/puppet/module_tool/errors.rb" -/bin/rm -Rf "${3}/puppet/indirector/errors.rb" +/bin/rm -Rf "${3}/puppet/module_tool/shared_behaviors.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/ldap.rb" +/bin/rm -Rf "${3}/puppet/module_tool/skeleton.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/active_record.rb" +/bin/rm -Rf "${3}/puppet/module_tool/dependency.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/exec.rb" +/bin/rm -Rf "${3}/puppet/module_tool/modulefile.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/store_configs.rb" +/bin/rm -Rf "${3}/puppet/module_tool/applications.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/yaml.rb" +/bin/rm -Rf "${3}/puppet/reference/metaparameter.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/rest.rb" +/bin/rm -Rf "${3}/puppet/reference/type.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/plain.rb" +/bin/rm -Rf "${3}/puppet/reference/network.rb" -/bin/rm -Rf "${3}/puppet/indirector/node/memory.rb" +/bin/rm -Rf "${3}/puppet/reference/indirection.rb" -/bin/rm -Rf "${3}/puppet/indirector/memory.rb" +/bin/rm -Rf "${3}/puppet/reference/report.rb" -/bin/rm -Rf "${3}/puppet/indirector/run/rest.rb" +/bin/rm -Rf "${3}/puppet/reference/function.rb" -/bin/rm -Rf "${3}/puppet/indirector/run/local.rb" +/bin/rm -Rf "${3}/puppet/reference/providers.rb" -/bin/rm -Rf "${3}/puppet/indirector/certificate_status.rb" +/bin/rm -Rf "${3}/puppet/reference/configuration.rb" -/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data.rb" +/bin/rm -Rf "${3}/puppet/vendor/require_vendored.rb" -/bin/rm -Rf "${3}/puppet/indirector/resource_type.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/LICENSE.txt" -/bin/rm -Rf "${3}/puppet/ssl.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/transform/to_integer_spec.rb" -/bin/rm -Rf "${3}/puppet/indirector.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/transform/base64_spec.rb" -/bin/rm -Rf "${3}/puppet/module.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb" -/bin/rm -Rf "${3}/puppet/interface.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/transform/to_float_spec.rb" -/bin/rm -Rf "${3}/puppet/file_bucket.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/transform/to_date_spec.rb" -/bin/rm -Rf "${3}/puppet/interface/option_builder.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/exploit.1.9.2.yaml" -/bin/rm -Rf "${3}/puppet/interface/documentation.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/spec_helper.rb" -/bin/rm -Rf "${3}/puppet/interface/action_builder.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/syck_resolver_spec.rb" -/bin/rm -Rf "${3}/puppet/interface/face_collection.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb" -/bin/rm -Rf "${3}/puppet/interface/action_manager.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/resolver_specs.rb" -/bin/rm -Rf "${3}/puppet/interface/action.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/support/exploitable_back_door.rb" -/bin/rm -Rf "${3}/puppet/interface/option_manager.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/psych_resolver_spec.rb" -/bin/rm -Rf "${3}/puppet/interface/option.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/spec/exploit.1.9.3.yaml" -/bin/rm -Rf "${3}/puppet/file_collection.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/README.md" -/bin/rm -Rf "${3}/puppet/node.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/Rakefile" -/bin/rm -Rf "${3}/puppet/application/catalog.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/Gemfile" -/bin/rm -Rf "${3}/puppet/application/agent.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/safe_yaml.gemspec" -/bin/rm -Rf "${3}/puppet/application/device.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/CHANGES.md" -/bin/rm -Rf "${3}/puppet/application/master.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_date.rb" -/bin/rm -Rf "${3}/puppet/application/kick.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_symbol.rb" -/bin/rm -Rf "${3}/puppet/application/man.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_boolean.rb" -/bin/rm -Rf "${3}/puppet/application/face_base.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_integer.rb" -/bin/rm -Rf "${3}/puppet/application/certificate_request.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_nil.rb" -/bin/rm -Rf "${3}/puppet/application/module.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/transformation_map.rb" -/bin/rm -Rf "${3}/puppet/application/instrumentation_listener.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_float.rb" -/bin/rm -Rf "${3}/puppet/application/node.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/psych_handler.rb" -/bin/rm -Rf "${3}/puppet/application/describe.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/deep.rb" -/bin/rm -Rf "${3}/puppet/application/resource.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/resolver.rb" -/bin/rm -Rf "${3}/puppet/application/certificate.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/version.rb" -/bin/rm -Rf "${3}/puppet/application/doc.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/syck_resolver.rb" -/bin/rm -Rf "${3}/puppet/application/file.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/safe_to_ruby_visitor.rb" -/bin/rm -Rf "${3}/puppet/application/key.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/transform.rb" -/bin/rm -Rf "${3}/puppet/application/facts.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/syck_node_monkeypatch.rb" -/bin/rm -Rf "${3}/puppet/application/inspect.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/psych_resolver.rb" -/bin/rm -Rf "${3}/puppet/application/cert.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/syck_hack.rb" -/bin/rm -Rf "${3}/puppet/application/config.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/parse/sexagesimal.rb" -/bin/rm -Rf "${3}/puppet/application/ca.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/parse/date.rb" -/bin/rm -Rf "${3}/puppet/application/indirection_base.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml/parse/hexadecimal.rb" -/bin/rm -Rf "${3}/puppet/application/help.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/lib/safe_yaml.rb" -/bin/rm -Rf "${3}/puppet/application/queue.rb" +/bin/rm -Rf "${3}/puppet/vendor/safe_yaml/run_specs_all_ruby_versions.sh" -/bin/rm -Rf "${3}/puppet/application/plugin.rb" +/bin/rm -Rf "${3}/puppet/vendor/load_safe_yaml.rb" -/bin/rm -Rf "${3}/puppet/application/parser.rb" +/bin/rm -Rf "${3}/puppet/type.rb" -/bin/rm -Rf "${3}/puppet/application/certificate_revocation_list.rb" +/bin/rm -Rf "${3}/puppet/network.rb" -/bin/rm -Rf "${3}/puppet/application/status.rb" +/bin/rm -Rf "${3}/puppet/file_bucket/file.rb" -/bin/rm -Rf "${3}/puppet/application/secret_agent.rb" +/bin/rm -Rf "${3}/puppet/file_bucket/dipper.rb" -/bin/rm -Rf "${3}/puppet/application/report.rb" +/bin/rm -Rf "${3}/puppet/configurer/plugin_handler.rb" -/bin/rm -Rf "${3}/puppet/application/instrumentation_probe.rb" +/bin/rm -Rf "${3}/puppet/configurer/downloader.rb" -/bin/rm -Rf "${3}/puppet/application/apply.rb" +/bin/rm -Rf "${3}/puppet/configurer/fact_handler.rb" -/bin/rm -Rf "${3}/puppet/application/filebucket.rb" +/bin/rm -Rf "${3}/puppet/type/ssh_authorized_key.rb" -/bin/rm -Rf "${3}/puppet/application/instrumentation_data.rb" +/bin/rm -Rf "${3}/puppet/type/augeas.rb" -/bin/rm -Rf "${3}/puppet/application/resource_type.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_contactgroup.rb" -/bin/rm -Rf "${3}/puppet/dsl.rb" +/bin/rm -Rf "${3}/puppet/type/router.rb" -/bin/rm -Rf "${3}/puppet/resource.rb" +/bin/rm -Rf "${3}/puppet/type/selmodule.rb" -/bin/rm -Rf "${3}/puppet/file_serving.rb" +/bin/rm -Rf "${3}/puppet/type/filebucket.rb" -/bin/rm -Rf "${3}/puppet/transportable.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_hostdependency.rb" -/bin/rm -Rf "${3}/puppet/provider.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_servicedependency.rb" -/bin/rm -Rf "${3}/puppet/parameter.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_hostgroup.rb" -/bin/rm -Rf "${3}/puppet/relationship.rb" +/bin/rm -Rf "${3}/puppet/type/service.rb" -/bin/rm -Rf "${3}/puppet/application.rb" +/bin/rm -Rf "${3}/puppet/type/k5login.rb" -/bin/rm -Rf "${3}/puppet/transaction/resource_harness.rb" +/bin/rm -Rf "${3}/puppet/type/exec.rb" -/bin/rm -Rf "${3}/puppet/transaction/event.rb" +/bin/rm -Rf "${3}/puppet/type/file/source.rb" -/bin/rm -Rf "${3}/puppet/transaction/event_manager.rb" +/bin/rm -Rf "${3}/puppet/type/file/selcontext.rb" -/bin/rm -Rf "${3}/puppet/transaction/report.rb" +/bin/rm -Rf "${3}/puppet/type/file/ensure.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_host.rb" +/bin/rm -Rf "${3}/puppet/type/file/content.rb" -/bin/rm -Rf "${3}/puppet/type/mcx.rb" +/bin/rm -Rf "${3}/puppet/type/file/mtime.rb" -/bin/rm -Rf "${3}/puppet/type/tidy.rb" +/bin/rm -Rf "${3}/puppet/type/file/type.rb" -/bin/rm -Rf "${3}/puppet/type/whit.rb" +/bin/rm -Rf "${3}/puppet/type/file/group.rb" -/bin/rm -Rf "${3}/puppet/type/ssh_authorized_key.rb" +/bin/rm -Rf "${3}/puppet/type/file/mode.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_hostdependency.rb" +/bin/rm -Rf "${3}/puppet/type/file/ctime.rb" -/bin/rm -Rf "${3}/puppet/type/exec.rb" +/bin/rm -Rf "${3}/puppet/type/file/checksum.rb" -/bin/rm -Rf "${3}/puppet/type/interface.rb" +/bin/rm -Rf "${3}/puppet/type/file/target.rb" -/bin/rm -Rf "${3}/puppet/type/macauthorization.rb" +/bin/rm -Rf "${3}/puppet/type/file/owner.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_serviceescalation.rb" +/bin/rm -Rf "${3}/puppet/type/zfs.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_hostextinfo.rb" +/bin/rm -Rf "${3}/puppet/type/component.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_servicegroup.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_command.rb" /bin/rm -Rf "${3}/puppet/type/group.rb" -/bin/rm -Rf "${3}/puppet/type/zpool.rb" - -/bin/rm -Rf "${3}/puppet/type/port.rb" - -/bin/rm -Rf "${3}/puppet/type/k5login.rb" +/bin/rm -Rf "${3}/puppet/type/mount.rb" -/bin/rm -Rf "${3}/puppet/type/maillist.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_hostextinfo.rb" -/bin/rm -Rf "${3}/puppet/type/selmodule.rb" +/bin/rm -Rf "${3}/puppet/type/cron.rb" -/bin/rm -Rf "${3}/puppet/type/file.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_hostescalation.rb" -/bin/rm -Rf "${3}/puppet/type/vlan.rb" +/bin/rm -Rf "${3}/puppet/type/schedule.rb" -/bin/rm -Rf "${3}/puppet/type/zfs.rb" +/bin/rm -Rf "${3}/puppet/type/resources.rb" -/bin/rm -Rf "${3}/puppet/type/notify.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_contact.rb" -/bin/rm -Rf "${3}/puppet/type/selboolean.rb" +/bin/rm -Rf "${3}/puppet/type/stage.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_servicedependency.rb" +/bin/rm -Rf "${3}/puppet/type/yumrepo.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_contact.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_host.rb" -/bin/rm -Rf "${3}/puppet/type/file/group.rb" +/bin/rm -Rf "${3}/puppet/type/file.rb" -/bin/rm -Rf "${3}/puppet/type/file/owner.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_timeperiod.rb" -/bin/rm -Rf "${3}/puppet/type/file/ctime.rb" +/bin/rm -Rf "${3}/puppet/type/port.rb" -/bin/rm -Rf "${3}/puppet/type/file/mtime.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_service.rb" -/bin/rm -Rf "${3}/puppet/type/file/target.rb" +/bin/rm -Rf "${3}/puppet/type/zpool.rb" -/bin/rm -Rf "${3}/puppet/type/file/mode.rb" +/bin/rm -Rf "${3}/puppet/type/tidy.rb" -/bin/rm -Rf "${3}/puppet/type/file/source.rb" +/bin/rm -Rf "${3}/puppet/type/mailalias.rb" -/bin/rm -Rf "${3}/puppet/type/file/type.rb" +/bin/rm -Rf "${3}/puppet/type/sshkey.rb" -/bin/rm -Rf "${3}/puppet/type/file/ensure.rb" +/bin/rm -Rf "${3}/puppet/type/user.rb" -/bin/rm -Rf "${3}/puppet/type/file/checksum.rb" +/bin/rm -Rf "${3}/puppet/type/host.rb" -/bin/rm -Rf "${3}/puppet/type/file/content.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_servicegroup.rb" -/bin/rm -Rf "${3}/puppet/type/file/selcontext.rb" +/bin/rm -Rf "${3}/puppet/type/vlan.rb" /bin/rm -Rf "${3}/puppet/type/zone.rb" -/bin/rm -Rf "${3}/puppet/type/sshkey.rb" - -/bin/rm -Rf "${3}/puppet/type/nagios_hostescalation.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_serviceextinfo.rb" /bin/rm -Rf "${3}/puppet/type/computer.rb" -/bin/rm -Rf "${3}/puppet/type/cron.rb" +/bin/rm -Rf "${3}/puppet/type/selboolean.rb" -/bin/rm -Rf "${3}/puppet/type/augeas.rb" +/bin/rm -Rf "${3}/puppet/type/nagios_serviceescalation.rb" -/bin/rm -Rf "${3}/puppet/type/component.rb" +/bin/rm -Rf "${3}/puppet/type/macauthorization.rb" -/bin/rm -Rf "${3}/puppet/type/scheduled_task.rb" +/bin/rm -Rf "${3}/puppet/type/interface.rb" -/bin/rm -Rf "${3}/puppet/type/resources.rb" +/bin/rm -Rf "${3}/puppet/type/maillist.rb" -/bin/rm -Rf "${3}/puppet/type/host.rb" +/bin/rm -Rf "${3}/puppet/type/package.rb" -/bin/rm -Rf "${3}/puppet/type/yumrepo.rb" +/bin/rm -Rf "${3}/puppet/type/mcx.rb" -/bin/rm -Rf "${3}/puppet/type/schedule.rb" +/bin/rm -Rf "${3}/puppet/type/whit.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_service.rb" +/bin/rm -Rf "${3}/puppet/type/notify.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_timeperiod.rb" +/bin/rm -Rf "${3}/puppet/type/scheduled_task.rb" -/bin/rm -Rf "${3}/puppet/type/stage.rb" +/bin/rm -Rf "${3}/puppet/indirector/status/local.rb" -/bin/rm -Rf "${3}/puppet/type/mailalias.rb" +/bin/rm -Rf "${3}/puppet/indirector/status/rest.rb" -/bin/rm -Rf "${3}/puppet/type/router.rb" +/bin/rm -Rf "${3}/puppet/indirector/report/yaml.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_command.rb" +/bin/rm -Rf "${3}/puppet/indirector/report/processor.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_contactgroup.rb" +/bin/rm -Rf "${3}/puppet/indirector/report/rest.rb" -/bin/rm -Rf "${3}/puppet/type/user.rb" +/bin/rm -Rf "${3}/puppet/indirector/status.rb" -/bin/rm -Rf "${3}/puppet/type/mount.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_metadata/selector.rb" -/bin/rm -Rf "${3}/puppet/type/service.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_metadata/file_server.rb" -/bin/rm -Rf "${3}/puppet/type/filebucket.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_metadata/file.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_serviceextinfo.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_metadata/rest.rb" -/bin/rm -Rf "${3}/puppet/type/package.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/selector.rb" -/bin/rm -Rf "${3}/puppet/type/nagios_hostgroup.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/file.rb" -/bin/rm -Rf "${3}/puppet/feature/ssh.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_bucket_file/rest.rb" -/bin/rm -Rf "${3}/puppet/feature/base.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_status/file.rb" -/bin/rm -Rf "${3}/puppet/feature/pson.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_status/rest.rb" -/bin/rm -Rf "${3}/puppet/feature/stomp.rb" +/bin/rm -Rf "${3}/puppet/indirector/key/ca.rb" -/bin/rm -Rf "${3}/puppet/feature/selinux.rb" +/bin/rm -Rf "${3}/puppet/indirector/key/file.rb" -/bin/rm -Rf "${3}/puppet/feature/rails.rb" +/bin/rm -Rf "${3}/puppet/indirector/key/disabled_ca.rb" -/bin/rm -Rf "${3}/puppet/feature/zlib.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_metadata.rb" -/bin/rm -Rf "${3}/puppet/feature/eventlog.rb" +/bin/rm -Rf "${3}/puppet/indirector/envelope.rb" -/bin/rm -Rf "${3}/puppet/feature/rubygems.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource/ral.rb" -/bin/rm -Rf "${3}/puppet/feature/rack.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource/store_configs.rb" -/bin/rm -Rf "${3}/puppet/reference/function.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource/active_record.rb" -/bin/rm -Rf "${3}/puppet/reference/metaparameter.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource/rest.rb" -/bin/rm -Rf "${3}/puppet/reference/indirection.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource/validator.rb" -/bin/rm -Rf "${3}/puppet/reference/type.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_status.rb" -/bin/rm -Rf "${3}/puppet/reference/network.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate/ca.rb" -/bin/rm -Rf "${3}/puppet/reference/providers.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate/file.rb" -/bin/rm -Rf "${3}/puppet/reference/configuration.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate/disabled_ca.rb" -/bin/rm -Rf "${3}/puppet/reference/report.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate/rest.rb" -/bin/rm -Rf "${3}/puppet/file_bucket/file.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource_type/parser.rb" -/bin/rm -Rf "${3}/puppet/file_bucket/dipper.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource_type/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/maillist/mailman.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/ca.rb" -/bin/rm -Rf "${3}/puppet/provider/confine_collection.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/file.rb" -/bin/rm -Rf "${3}/puppet/provider/cron/crontab.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/disabled_ca.rb" -/bin/rm -Rf "${3}/puppet/provider/ldap.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_revocation_list/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/nameservice/objectadd.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/inventory_active_record.rb" -/bin/rm -Rf "${3}/puppet/provider/nameservice/pw.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/store_configs.rb" -/bin/rm -Rf "${3}/puppet/provider/nameservice/directoryservice.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/network_device.rb" -/bin/rm -Rf "${3}/puppet/provider/zpool/solaris.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/couch.rb" -/bin/rm -Rf "${3}/puppet/provider/computer/computer.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/yaml.rb" -/bin/rm -Rf "${3}/puppet/provider/exec.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/memory.rb" -/bin/rm -Rf "${3}/puppet/provider/interface/base.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/facter.rb" -/bin/rm -Rf "${3}/puppet/provider/interface/cisco.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/active_record.rb" -/bin/rm -Rf "${3}/puppet/provider/group/ldap.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/group/aix.rb" +/bin/rm -Rf "${3}/puppet/indirector/facts/inventory_service.rb" -/bin/rm -Rf "${3}/puppet/provider/group/pw.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener/local.rb" -/bin/rm -Rf "${3}/puppet/provider/group/groupadd.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/group/directoryservice.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/static_compiler.rb" -/bin/rm -Rf "${3}/puppet/provider/group/windows_adsi.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/store_configs.rb" -/bin/rm -Rf "${3}/puppet/provider/confine.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/queue.rb" -/bin/rm -Rf "${3}/puppet/provider/service/redhat.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/yaml.rb" -/bin/rm -Rf "${3}/puppet/provider/service/freebsd.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/compiler.rb" -/bin/rm -Rf "${3}/puppet/provider/service/runit.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/active_record.rb" -/bin/rm -Rf "${3}/puppet/provider/service/base.rb" +/bin/rm -Rf "${3}/puppet/indirector/catalog/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/service/smf.rb" +/bin/rm -Rf "${3}/puppet/indirector/exec.rb" -/bin/rm -Rf "${3}/puppet/provider/service/bsd.rb" +/bin/rm -Rf "${3}/puppet/indirector/store_configs.rb" -/bin/rm -Rf "${3}/puppet/provider/service/systemd.rb" +/bin/rm -Rf "${3}/puppet/indirector/ldap.rb" -/bin/rm -Rf "${3}/puppet/provider/service/gentoo.rb" +/bin/rm -Rf "${3}/puppet/indirector/inventory/yaml.rb" -/bin/rm -Rf "${3}/puppet/provider/service/launchd.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_server.rb" -/bin/rm -Rf "${3}/puppet/provider/service/openrc.rb" +/bin/rm -Rf "${3}/puppet/indirector/face.rb" -/bin/rm -Rf "${3}/puppet/provider/service/daemontools.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_listener.rb" -/bin/rm -Rf "${3}/puppet/provider/service/upstart.rb" +/bin/rm -Rf "${3}/puppet/indirector/couch.rb" -/bin/rm -Rf "${3}/puppet/provider/service/windows.rb" +/bin/rm -Rf "${3}/puppet/indirector/errors.rb" -/bin/rm -Rf "${3}/puppet/provider/service/src.rb" +/bin/rm -Rf "${3}/puppet/indirector/terminus.rb" -/bin/rm -Rf "${3}/puppet/provider/service/init.rb" +/bin/rm -Rf "${3}/puppet/indirector/queue.rb" -/bin/rm -Rf "${3}/puppet/provider/service/service.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/exec.rb" -/bin/rm -Rf "${3}/puppet/provider/service/debian.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/store_configs.rb" -/bin/rm -Rf "${3}/puppet/provider/mount/parsed.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/ldap.rb" -/bin/rm -Rf "${3}/puppet/provider/parsedfile.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/yaml.rb" -/bin/rm -Rf "${3}/puppet/provider/macauthorization/macauthorization.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/memory.rb" -/bin/rm -Rf "${3}/puppet/provider/file/posix.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/active_record.rb" -/bin/rm -Rf "${3}/puppet/provider/file/windows.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/plain.rb" -/bin/rm -Rf "${3}/puppet/provider/zone/solaris.rb" +/bin/rm -Rf "${3}/puppet/indirector/node/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/scheduled_task/win32_taskscheduler.rb" +/bin/rm -Rf "${3}/puppet/indirector/yaml.rb" -/bin/rm -Rf "${3}/puppet/provider/zfs/solaris.rb" +/bin/rm -Rf "${3}/puppet/indirector/indirection.rb" -/bin/rm -Rf "${3}/puppet/provider/augeas/augeas.rb" +/bin/rm -Rf "${3}/puppet/indirector/memory.rb" -/bin/rm -Rf "${3}/puppet/provider/mailalias/aliases.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_content.rb" -/bin/rm -Rf "${3}/puppet/provider/network_device.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe.rb" -/bin/rm -Rf "${3}/puppet/provider/confine/feature.rb" +/bin/rm -Rf "${3}/puppet/indirector/resource_type.rb" -/bin/rm -Rf "${3}/puppet/provider/confine/variable.rb" +/bin/rm -Rf "${3}/puppet/indirector/code.rb" -/bin/rm -Rf "${3}/puppet/provider/confine/exists.rb" +/bin/rm -Rf "${3}/puppet/indirector/run/local.rb" -/bin/rm -Rf "${3}/puppet/provider/confine/false.rb" +/bin/rm -Rf "${3}/puppet/indirector/run/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/confine/true.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe/local.rb" -/bin/rm -Rf "${3}/puppet/provider/package/fink.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_probe/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/package/ports.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data/local.rb" -/bin/rm -Rf "${3}/puppet/provider/package/yum.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/package/zypper.rb" +/bin/rm -Rf "${3}/puppet/indirector/request.rb" -/bin/rm -Rf "${3}/puppet/provider/package/freebsd.rb" +/bin/rm -Rf "${3}/puppet/indirector/active_record.rb" -/bin/rm -Rf "${3}/puppet/provider/package/blastwave.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_request/ca.rb" -/bin/rm -Rf "${3}/puppet/provider/package/gem.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_request/file.rb" -/bin/rm -Rf "${3}/puppet/provider/package/pkg.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_request/disabled_ca.rb" -/bin/rm -Rf "${3}/puppet/provider/package/portupgrade.rb" +/bin/rm -Rf "${3}/puppet/indirector/certificate_request/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/package/portage.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_content/selector.rb" -/bin/rm -Rf "${3}/puppet/provider/package/aptrpm.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_content/file_server.rb" -/bin/rm -Rf "${3}/puppet/provider/package/hpux.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_content/file.rb" -/bin/rm -Rf "${3}/puppet/provider/package/rug.rb" +/bin/rm -Rf "${3}/puppet/indirector/file_content/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/package/pkgdmg.rb" +/bin/rm -Rf "${3}/puppet/indirector/instrumentation_data.rb" -/bin/rm -Rf "${3}/puppet/provider/package/aptitude.rb" +/bin/rm -Rf "${3}/puppet/indirector/plain.rb" -/bin/rm -Rf "${3}/puppet/provider/package/dpkg.rb" +/bin/rm -Rf "${3}/puppet/indirector/rest.rb" -/bin/rm -Rf "${3}/puppet/provider/package/pacman.rb" +/bin/rm -Rf "${3}/puppet/indirector/direct_file_server.rb" -/bin/rm -Rf "${3}/puppet/provider/package/appdmg.rb" +/bin/rm -Rf "${3}/puppet/indirector/ssl_file.rb" -/bin/rm -Rf "${3}/puppet/provider/package/pip.rb" +/bin/rm -Rf "${3}/puppet/parser/relationship.rb" -/bin/rm -Rf "${3}/puppet/provider/package/sunfreeware.rb" +/bin/rm -Rf "${3}/puppet/parser/resource.rb" -/bin/rm -Rf "${3}/puppet/provider/package/aix.rb" +/bin/rm -Rf "${3}/puppet/parser/grammar.ra" -/bin/rm -Rf "${3}/puppet/provider/package/msi.rb" +/bin/rm -Rf "${3}/puppet/parser/resource/param.rb" -/bin/rm -Rf "${3}/puppet/provider/package/nim.rb" +/bin/rm -Rf "${3}/puppet/parser/lexer.rb" -/bin/rm -Rf "${3}/puppet/provider/package/pkgutil.rb" +/bin/rm -Rf "${3}/puppet/parser/type_loader.rb" -/bin/rm -Rf "${3}/puppet/provider/package/macports.rb" +/bin/rm -Rf "${3}/puppet/parser/functions.rb" -/bin/rm -Rf "${3}/puppet/provider/package/urpmi.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/minus.rb" -/bin/rm -Rf "${3}/puppet/provider/package/up2date.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/relationship.rb" -/bin/rm -Rf "${3}/puppet/provider/package/apple.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resource.rb" -/bin/rm -Rf "${3}/puppet/provider/package/yumhelper.py" +/bin/rm -Rf "${3}/puppet/parser/ast/casestatement.rb" -/bin/rm -Rf "${3}/puppet/provider/package/apt.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/match_operator.rb" -/bin/rm -Rf "${3}/puppet/provider/package/sun.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/asthash.rb" -/bin/rm -Rf "${3}/puppet/provider/package/rpm.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resource_override.rb" -/bin/rm -Rf "${3}/puppet/provider/package/openbsd.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/nop.rb" -/bin/rm -Rf "${3}/puppet/provider/ssh_authorized_key/parsed.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/collexpr.rb" -/bin/rm -Rf "${3}/puppet/provider/confiner.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/selector.rb" -/bin/rm -Rf "${3}/puppet/provider/exec/posix.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/not.rb" -/bin/rm -Rf "${3}/puppet/provider/exec/windows.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/boolean_operator.rb" -/bin/rm -Rf "${3}/puppet/provider/exec/shell.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resource_defaults.rb" -/bin/rm -Rf "${3}/puppet/provider/vlan/cisco.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/ifstatement.rb" -/bin/rm -Rf "${3}/puppet/provider/selboolean/getsetsebool.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/top_level_construct.rb" -/bin/rm -Rf "${3}/puppet/provider/mcx/mcxcontent.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/collection.rb" -/bin/rm -Rf "${3}/puppet/provider/cisco.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/comparison_operator.rb" -/bin/rm -Rf "${3}/puppet/provider/nameservice.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resource_reference.rb" -/bin/rm -Rf "${3}/puppet/provider/naginator.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/vardef.rb" -/bin/rm -Rf "${3}/puppet/provider/host/parsed.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resource_instance.rb" -/bin/rm -Rf "${3}/puppet/provider/selmodule/semodule.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/node.rb" -/bin/rm -Rf "${3}/puppet/provider/mount.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/else.rb" -/bin/rm -Rf "${3}/puppet/provider/aixobject.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/definition.rb" -/bin/rm -Rf "${3}/puppet/provider/sshkey/parsed.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/branch.rb" -/bin/rm -Rf "${3}/puppet/provider/user/ldap.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/function.rb" -/bin/rm -Rf "${3}/puppet/provider/user/hpux.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/leaf.rb" -/bin/rm -Rf "${3}/puppet/provider/user/aix.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/caseopt.rb" -/bin/rm -Rf "${3}/puppet/provider/user/pw.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/in_operator.rb" -/bin/rm -Rf "${3}/puppet/provider/user/useradd.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/tag.rb" -/bin/rm -Rf "${3}/puppet/provider/user/directoryservice.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/astarray.rb" -/bin/rm -Rf "${3}/puppet/provider/user/user_role_add.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/arithmetic_operator.rb" -/bin/rm -Rf "${3}/puppet/provider/user/windows_adsi.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/resourceparam.rb" -/bin/rm -Rf "${3}/puppet/provider/port/parsed.rb" +/bin/rm -Rf "${3}/puppet/parser/ast/hostclass.rb" -/bin/rm -Rf "${3}/puppet/provider/package.rb" +/bin/rm -Rf "${3}/puppet/parser/parser.rb" -/bin/rm -Rf "${3}/puppet/util/execution_stub.rb" +/bin/rm -Rf "${3}/puppet/parser/collector.rb" -/bin/rm -Rf "${3}/puppet/util/posix.rb" +/bin/rm -Rf "${3}/puppet/parser/files.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/cisco/device.rb" +/bin/rm -Rf "${3}/puppet/parser/templatewrapper.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/cisco/interface.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/regsubst.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/cisco/facts.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/versioncmp.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/base.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/split.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/transport/ssh.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/inline_template.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/transport/base.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/require.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/transport/telnet.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/realize.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/ipcalc.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/search.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/config.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/defined.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/transport.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/template.rb" -/bin/rm -Rf "${3}/puppet/util/network_device/cisco.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/fail.rb" -/bin/rm -Rf "${3}/puppet/util/filetype.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/sha1.rb" -/bin/rm -Rf "${3}/puppet/util/ldap/manager.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/fqdn_rand.rb" -/bin/rm -Rf "${3}/puppet/util/ldap/generator.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/file.rb" -/bin/rm -Rf "${3}/puppet/util/ldap/connection.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/include.rb" -/bin/rm -Rf "${3}/puppet/util/monkey_patches.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/create_resources.rb" -/bin/rm -Rf "${3}/puppet/util/execution.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/tagged.rb" -/bin/rm -Rf "${3}/puppet/util/suidmanager.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/shellquote.rb" -/bin/rm -Rf "${3}/puppet/util/graph.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/generate.rb" -/bin/rm -Rf "${3}/puppet/util/docs.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/extlookup.rb" -/bin/rm -Rf "${3}/puppet/util/pson.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/tag.rb" -/bin/rm -Rf "${3}/puppet/util/terminal.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/md5.rb" -/bin/rm -Rf "${3}/puppet/util/ldap.rb" +/bin/rm -Rf "${3}/puppet/parser/functions/sprintf.rb" -/bin/rm -Rf "${3}/puppet/util/queue/stomp.rb" +/bin/rm -Rf "${3}/puppet/parser/yaml_trimmer.rb" -/bin/rm -Rf "${3}/puppet/util/autoload.rb" +/bin/rm -Rf "${3}/puppet/parser/ast.rb" -/bin/rm -Rf "${3}/puppet/util/file_locking.rb" +/bin/rm -Rf "${3}/puppet/parser/compiler.rb" -/bin/rm -Rf "${3}/puppet/util/user_attr.rb" +/bin/rm -Rf "${3}/puppet/parser/parser_support.rb" -/bin/rm -Rf "${3}/puppet/util/settings/file_setting.rb" +/bin/rm -Rf "${3}/puppet/parser/scope.rb" -/bin/rm -Rf "${3}/puppet/util/settings/boolean_setting.rb" +/bin/rm -Rf "${3}/puppet/parser/makefile" -/bin/rm -Rf "${3}/puppet/util/settings/setting.rb" +/bin/rm -Rf "${3}/puppet/error.rb" -/bin/rm -Rf "${3}/puppet/util/feature.rb" +/bin/rm -Rf "${3}/puppet/face.rb" -/bin/rm -Rf "${3}/puppet/util/command_line.rb" +/bin/rm -Rf "${3}/puppet/run.rb" -/bin/rm -Rf "${3}/puppet/util/log.rb" +/bin/rm -Rf "${3}/puppet/simple_graph.rb" -/bin/rm -Rf "${3}/puppet/util/methodhelper.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate_revocation_list.rb" -/bin/rm -Rf "${3}/puppet/util/autoload/file_cache.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate_request.rb" -/bin/rm -Rf "${3}/puppet/util/log/destination.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate_authority/interface.rb" -/bin/rm -Rf "${3}/puppet/util/log/destinations.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate_authority.rb" -/bin/rm -Rf "${3}/puppet/util/fileparsing.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/instrumentable.rb" +/bin/rm -Rf "${3}/puppet/ssl/certificate_factory.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/indirection_probe.rb" +/bin/rm -Rf "${3}/puppet/ssl/base.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/listeners/log.rb" +/bin/rm -Rf "${3}/puppet/ssl/host.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/listeners/performance.rb" +/bin/rm -Rf "${3}/puppet/ssl/inventory.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/data.rb" +/bin/rm -Rf "${3}/puppet/ssl/key.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation/listener.rb" +/bin/rm -Rf "${3}/puppet/dsl.rb" -/bin/rm -Rf "${3}/puppet/util/checksums.rb" +/bin/rm -Rf "${3}/puppet/ssl.rb" -/bin/rm -Rf "${3}/puppet/util/metric.rb" +/bin/rm -Rf "${3}/puppet/indirector.rb" -/bin/rm -Rf "${3}/puppet/util/rdoc/generators/template/puppet/puppet.rb" +/bin/rm -Rf "${3}/puppet/node/environment.rb" -/bin/rm -Rf "${3}/puppet/util/rdoc/generators/puppet_generator.rb" +/bin/rm -Rf "${3}/puppet/node/facts.rb" -/bin/rm -Rf "${3}/puppet/util/rdoc/parser.rb" +/bin/rm -Rf "${3}/puppet/node/inventory.rb" -/bin/rm -Rf "${3}/puppet/util/rdoc/code_objects.rb" +/bin/rm -Rf "${3}/puppet/interface/option_builder.rb" -/bin/rm -Rf "${3}/puppet/util/reference.rb" +/bin/rm -Rf "${3}/puppet/interface/option_manager.rb" -/bin/rm -Rf "${3}/puppet/util/diff.rb" +/bin/rm -Rf "${3}/puppet/interface/documentation.rb" -/bin/rm -Rf "${3}/puppet/util/run_mode.rb" +/bin/rm -Rf "${3}/puppet/interface/option.rb" -/bin/rm -Rf "${3}/puppet/util/platform.rb" +/bin/rm -Rf "${3}/puppet/interface/action.rb" -/bin/rm -Rf "${3}/puppet/util/colors.rb" +/bin/rm -Rf "${3}/puppet/interface/face_collection.rb" -/bin/rm -Rf "${3}/puppet/util/windows.rb" +/bin/rm -Rf "${3}/puppet/interface/action_manager.rb" -/bin/rm -Rf "${3}/puppet/util/instrumentation.rb" +/bin/rm -Rf "${3}/puppet/interface/action_builder.rb" -/bin/rm -Rf "${3}/puppet/util/resource_template.rb" +/bin/rm -Rf "${3}/puppet/property.rb" -/bin/rm -Rf "${3}/puppet/util/warnings.rb" +/bin/rm -Rf "${3}/puppet/test/test_helper.rb" -/bin/rm -Rf "${3}/puppet/util/constant_inflector.rb" +/bin/rm -Rf "${3}/puppet/parameter.rb" -/bin/rm -Rf "${3}/puppet/util/pidlock.rb" +/bin/rm -Rf "${3}/puppet/application/face_base.rb" -/bin/rm -Rf "${3}/puppet/util/subclass_loader.rb" +/bin/rm -Rf "${3}/puppet/application/ca.rb" -/bin/rm -Rf "${3}/puppet/util/logging.rb" +/bin/rm -Rf "${3}/puppet/application/device.rb" -/bin/rm -Rf "${3}/puppet/util/adsi.rb" +/bin/rm -Rf "${3}/puppet/application/certificate_revocation_list.rb" -/bin/rm -Rf "${3}/puppet/util/network_device.rb" +/bin/rm -Rf "${3}/puppet/application/resource.rb" -/bin/rm -Rf "${3}/puppet/util/queue.rb" +/bin/rm -Rf "${3}/puppet/application/module.rb" -/bin/rm -Rf "${3}/puppet/util/storage.rb" +/bin/rm -Rf "${3}/puppet/application/plugin.rb" -/bin/rm -Rf "${3}/puppet/util/tagging.rb" +/bin/rm -Rf "${3}/puppet/application/config.rb" -/bin/rm -Rf "${3}/puppet/util/retryaction.rb" +/bin/rm -Rf "${3}/puppet/application/indirection_base.rb" -/bin/rm -Rf "${3}/puppet/util/backups.rb" +/bin/rm -Rf "${3}/puppet/application/status.rb" -/bin/rm -Rf "${3}/puppet/util/zaml.rb" +/bin/rm -Rf "${3}/puppet/application/filebucket.rb" -/bin/rm -Rf "${3}/puppet/util/classgen.rb" +/bin/rm -Rf "${3}/puppet/application/certificate_request.rb" -/bin/rm -Rf "${3}/puppet/util/selinux.rb" +/bin/rm -Rf "${3}/puppet/application/cert.rb" -/bin/rm -Rf "${3}/puppet/util/log_paths.rb" +/bin/rm -Rf "${3}/puppet/application/man.rb" -/bin/rm -Rf "${3}/puppet/util/inline_docs.rb" +/bin/rm -Rf "${3}/puppet/application/doc.rb" -/bin/rm -Rf "${3}/puppet/util/rdoc.rb" +/bin/rm -Rf "${3}/puppet/application/certificate.rb" -/bin/rm -Rf "${3}/puppet/util/loadedfile.rb" +/bin/rm -Rf "${3}/puppet/application/instrumentation_listener.rb" -/bin/rm -Rf "${3}/puppet/util/nagios_maker.rb" +/bin/rm -Rf "${3}/puppet/application/queue.rb" -/bin/rm -Rf "${3}/puppet/util/plugins.rb" +/bin/rm -Rf "${3}/puppet/application/apply.rb" -/bin/rm -Rf "${3}/puppet/util/settings.rb" +/bin/rm -Rf "${3}/puppet/application/file.rb" -/bin/rm -Rf "${3}/puppet/util/inifile.rb" +/bin/rm -Rf "${3}/puppet/application/agent.rb" -/bin/rm -Rf "${3}/puppet/util/metaid.rb" +/bin/rm -Rf "${3}/puppet/application/inspect.rb" -/bin/rm -Rf "${3}/puppet/util/cacher.rb" +/bin/rm -Rf "${3}/puppet/application/help.rb" -/bin/rm -Rf "${3}/puppet/util/windows/sid.rb" +/bin/rm -Rf "${3}/puppet/application/parser.rb" -/bin/rm -Rf "${3}/puppet/util/windows/error.rb" +/bin/rm -Rf "${3}/puppet/application/instrumentation_probe.rb" -/bin/rm -Rf "${3}/puppet/util/windows/file.rb" +/bin/rm -Rf "${3}/puppet/application/describe.rb" -/bin/rm -Rf "${3}/puppet/util/windows/process.rb" +/bin/rm -Rf "${3}/puppet/application/secret_agent.rb" -/bin/rm -Rf "${3}/puppet/util/windows/user.rb" +/bin/rm -Rf "${3}/puppet/application/resource_type.rb" -/bin/rm -Rf "${3}/puppet/util/windows/security.rb" +/bin/rm -Rf "${3}/puppet/application/node.rb" -/bin/rm -Rf "${3}/puppet/util/provider_features.rb" +/bin/rm -Rf "${3}/puppet/application/facts.rb" -/bin/rm -Rf "${3}/puppet/util/rails/cache_accumulator.rb" +/bin/rm -Rf "${3}/puppet/application/report.rb" -/bin/rm -Rf "${3}/puppet/util/rails/collection_merger.rb" +/bin/rm -Rf "${3}/puppet/application/catalog.rb" -/bin/rm -Rf "${3}/puppet/util/rails/reference_serializer.rb" +/bin/rm -Rf "${3}/puppet/application/master.rb" -/bin/rm -Rf "${3}/puppet/util/symbolic_file_mode.rb" +/bin/rm -Rf "${3}/puppet/application/instrumentation_data.rb" -/bin/rm -Rf "${3}/puppet/util/errors.rb" +/bin/rm -Rf "${3}/puppet/application/kick.rb" -/bin/rm -Rf "${3}/puppet/util/package.rb" +/bin/rm -Rf "${3}/puppet/application/key.rb" -/bin/rm -Rf "${3}/puppet/util/instance_loader.rb" +/bin/rm -Rf "${3}/puppet/agent.rb" -/bin/rm -Rf "${3}/puppet/reports/log.rb" +/bin/rm -Rf "${3}/puppet/rb_tree_map.rb" -/bin/rm -Rf "${3}/puppet/reports/store.rb" +/bin/rm -Rf "${3}/puppet/forge.rb" -/bin/rm -Rf "${3}/puppet/reports/http.rb" +/bin/rm -Rf "${3}/puppet/parser.rb" -/bin/rm -Rf "${3}/puppet/reports/tagmail.rb" +/bin/rm -Rf "${3}/puppet/transaction/event.rb" -/bin/rm -Rf "${3}/puppet/reports/rrdgraph.rb" +/bin/rm -Rf "${3}/puppet/transaction/resource_harness.rb" -/bin/rm -Rf "${3}/puppet/test/test_helper.rb" +/bin/rm -Rf "${3}/puppet/transaction/report.rb" -/bin/rm -Rf "${3}/puppet/daemon.rb" +/bin/rm -Rf "${3}/puppet/transaction/event_manager.rb" -/bin/rm -Rf "${3}/puppet/network/http/mongrel.rb" +/bin/rm -Rf "${3}/puppet/file_serving.rb" -/bin/rm -Rf "${3}/puppet/network/http/rack/httphandler.rb" +/bin/rm -Rf "${3}/puppet/daemon.rb" -/bin/rm -Rf "${3}/puppet/network/http/rack/rest.rb" +/bin/rm -Rf "${3}/puppet/forge/cache.rb" -/bin/rm -Rf "${3}/puppet/network/http/rack/xmlrpc.rb" +/bin/rm -Rf "${3}/puppet/forge/repository.rb" -/bin/rm -Rf "${3}/puppet/network/http/api/v1.rb" +/bin/rm -Rf "${3}/puppet/file_bucket.rb" -/bin/rm -Rf "${3}/puppet/network/http/compression.rb" +/bin/rm -Rf "${3}/puppet/transaction.rb" -/bin/rm -Rf "${3}/puppet/network/http/webrick/rest.rb" +/bin/rm -Rf "${3}/puppet/file_collection.rb" -/bin/rm -Rf "${3}/puppet/network/http/mongrel/rest.rb" +/bin/rm -Rf "${3}/puppet/vendor.rb" -/bin/rm -Rf "${3}/puppet/network/http/api.rb" +/bin/rm -Rf "${3}/puppet/node.rb" -/bin/rm -Rf "${3}/puppet/network/http/handler.rb" +/bin/rm -Rf "${3}/puppet/property/ensure.rb" -/bin/rm -Rf "${3}/puppet/network/http/webrick.rb" +/bin/rm -Rf "${3}/puppet/property/list.rb" -/bin/rm -Rf "${3}/puppet/network/http/rack.rb" +/bin/rm -Rf "${3}/puppet/property/ordered_list.rb" -/bin/rm -Rf "${3}/puppet/network/handler/runner.rb" +/bin/rm -Rf "${3}/puppet/property/keyvalue.rb" -/bin/rm -Rf "${3}/puppet/network/handler/master.rb" +/bin/rm -Rf "${3}/puppet/file_system.rb" -/bin/rm -Rf "${3}/puppet/network/handler/ca.rb" +/bin/rm -Rf "${3}/puppet/file_collection/lookup.rb" -/bin/rm -Rf "${3}/puppet/network/handler/status.rb" +/bin/rm -Rf "${3}/puppet/file_system/path_pattern.rb" -/bin/rm -Rf "${3}/puppet/network/handler/report.rb" +/bin/rm -Rf "${3}/puppet/dsl/resource_api.rb" -/bin/rm -Rf "${3}/puppet/network/handler/fileserver.rb" +/bin/rm -Rf "${3}/puppet/dsl/resource_type_api.rb" -/bin/rm -Rf "${3}/puppet/network/handler/filebucket.rb" +/bin/rm -Rf "${3}/puppet/util/constant_inflector.rb" -/bin/rm -Rf "${3}/puppet/network/http_server.rb" +/bin/rm -Rf "${3}/puppet/util/rdoc.rb" -/bin/rm -Rf "${3}/puppet/network/rights.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/listener.rb" -/bin/rm -Rf "${3}/puppet/network/rest_controller.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/instrumentable.rb" -/bin/rm -Rf "${3}/puppet/network/authorization.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/data.rb" -/bin/rm -Rf "${3}/puppet/network/formats.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/listeners/performance.rb" -/bin/rm -Rf "${3}/puppet/network/format_handler.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/listeners/log.rb" -/bin/rm -Rf "${3}/puppet/network/rest_authconfig.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation/indirection_probe.rb" -/bin/rm -Rf "${3}/puppet/network/xmlrpc/processor.rb" +/bin/rm -Rf "${3}/puppet/util/cacher.rb" -/bin/rm -Rf "${3}/puppet/network/xmlrpc/webrick_servlet.rb" +/bin/rm -Rf "${3}/puppet/util/checksums.rb" -/bin/rm -Rf "${3}/puppet/network/xmlrpc/server.rb" +/bin/rm -Rf "${3}/puppet/util/terminal.rb" -/bin/rm -Rf "${3}/puppet/network/http.rb" +/bin/rm -Rf "${3}/puppet/util/pidlock.rb" -/bin/rm -Rf "${3}/puppet/network/rest_authorization.rb" +/bin/rm -Rf "${3}/puppet/util/plugins.rb" -/bin/rm -Rf "${3}/puppet/network/http_server/mongrel.rb" +/bin/rm -Rf "${3}/puppet/util/suidmanager.rb" -/bin/rm -Rf "${3}/puppet/network/server.rb" +/bin/rm -Rf "${3}/puppet/util/storage.rb" -/bin/rm -Rf "${3}/puppet/network/client_request.rb" +/bin/rm -Rf "${3}/puppet/util/metaid.rb" -/bin/rm -Rf "${3}/puppet/network/format.rb" +/bin/rm -Rf "${3}/puppet/util/tagging.rb" -/bin/rm -Rf "${3}/puppet/network/http_pool.rb" +/bin/rm -Rf "${3}/puppet/util/graph.rb" -/bin/rm -Rf "${3}/puppet/network/handler.rb" +/bin/rm -Rf "${3}/puppet/util/retryaction.rb" -/bin/rm -Rf "${3}/puppet/network/authconfig.rb" +/bin/rm -Rf "${3}/puppet/util/run_mode.rb" -/bin/rm -Rf "${3}/puppet/network/authstore.rb" +/bin/rm -Rf "${3}/puppet/util/filetype.rb" -/bin/rm -Rf "${3}/puppet/util.rb" +/bin/rm -Rf "${3}/puppet/util/metric.rb" -/bin/rm -Rf "${3}/puppet/external/nagios/base.rb" +/bin/rm -Rf "${3}/puppet/util/autoload.rb" -/bin/rm -Rf "${3}/puppet/external/nagios/grammar.ry" +/bin/rm -Rf "${3}/puppet/util/ldap.rb" -/bin/rm -Rf "${3}/puppet/external/nagios/parser.rb" +/bin/rm -Rf "${3}/puppet/util/network_device.rb" -/bin/rm -Rf "${3}/puppet/external/nagios/makefile" +/bin/rm -Rf "${3}/puppet/util/adsi.rb" -/bin/rm -Rf "${3}/puppet/external/pson/version.rb" +/bin/rm -Rf "${3}/puppet/util/zaml.rb" -/bin/rm -Rf "${3}/puppet/external/pson/common.rb" +/bin/rm -Rf "${3}/puppet/util/queue/stomp.rb" -/bin/rm -Rf "${3}/puppet/external/pson/pure.rb" +/bin/rm -Rf "${3}/puppet/util/user_attr.rb" -/bin/rm -Rf "${3}/puppet/external/pson/pure/parser.rb" +/bin/rm -Rf "${3}/puppet/util/execution_stub.rb" -/bin/rm -Rf "${3}/puppet/external/pson/pure/generator.rb" +/bin/rm -Rf "${3}/puppet/util/subclass_loader.rb" -/bin/rm -Rf "${3}/puppet/external/nagios.rb" +/bin/rm -Rf "${3}/puppet/util/docs.rb" -/bin/rm -Rf "${3}/puppet/external/lock.rb" +/bin/rm -Rf "${3}/puppet/util/diff.rb" -/bin/rm -Rf "${3}/puppet/external/dot.rb" +/bin/rm -Rf "${3}/puppet/util/ldap/manager.rb" -/bin/rm -Rf "${3}/puppet/external/base64.rb" +/bin/rm -Rf "${3}/puppet/util/ldap/connection.rb" -/bin/rm -Rf "${3}/puppet/parser.rb" +/bin/rm -Rf "${3}/puppet/util/ldap/generator.rb" -/bin/rm -Rf "${3}/puppet/metatype/manager.rb" +/bin/rm -Rf "${3}/puppet/util/loadedfile.rb" -/bin/rm -Rf "${3}/puppet/file_serving/base.rb" +/bin/rm -Rf "${3}/puppet/util/windows/process.rb" -/bin/rm -Rf "${3}/puppet/file_serving/configuration/parser.rb" +/bin/rm -Rf "${3}/puppet/util/windows/error.rb" -/bin/rm -Rf "${3}/puppet/file_serving/mount/file.rb" +/bin/rm -Rf "${3}/puppet/util/windows/file.rb" -/bin/rm -Rf "${3}/puppet/file_serving/mount/plugins.rb" +/bin/rm -Rf "${3}/puppet/util/windows/user.rb" -/bin/rm -Rf "${3}/puppet/file_serving/mount/modules.rb" +/bin/rm -Rf "${3}/puppet/util/windows/security.rb" -/bin/rm -Rf "${3}/puppet/file_serving/fileset.rb" +/bin/rm -Rf "${3}/puppet/util/windows/sid.rb" -/bin/rm -Rf "${3}/puppet/file_serving/terminus_selector.rb" +/bin/rm -Rf "${3}/puppet/util/methodhelper.rb" -/bin/rm -Rf "${3}/puppet/file_serving/configuration.rb" +/bin/rm -Rf "${3}/puppet/util/logging.rb" -/bin/rm -Rf "${3}/puppet/file_serving/metadata.rb" +/bin/rm -Rf "${3}/puppet/util/errors.rb" -/bin/rm -Rf "${3}/puppet/file_serving/terminus_helper.rb" +/bin/rm -Rf "${3}/puppet/util/queue.rb" -/bin/rm -Rf "${3}/puppet/file_serving/mount.rb" +/bin/rm -Rf "${3}/puppet/util/settings.rb" -/bin/rm -Rf "${3}/puppet/file_serving/content.rb" +/bin/rm -Rf "${3}/puppet/util/log/destination.rb" -/bin/rm -Rf "${3}/puppet/file_collection/lookup.rb" +/bin/rm -Rf "${3}/puppet/util/log/destinations.rb" -/bin/rm -Rf "${3}/puppet/configurer.rb" +/bin/rm -Rf "${3}/puppet/util/inline_docs.rb" -/bin/rm -Rf "${3}/puppet/forge/repository.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/config.rb" -/bin/rm -Rf "${3}/puppet/forge/cache.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/cisco/device.rb" -/bin/rm -Rf "${3}/puppet/type.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/cisco/facts.rb" -/bin/rm -Rf "${3}/puppet/rb_tree_map.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/cisco/interface.rb" -/bin/rm -Rf "${3}/puppet/dsl/resource_type_api.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/cisco.rb" -/bin/rm -Rf "${3}/puppet/dsl/resource_api.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/ipcalc.rb" -/bin/rm -Rf "${3}/puppet/agent/locker.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/transport.rb" -/bin/rm -Rf "${3}/puppet/face/catalog.rb" +/bin/rm -Rf "${3}/puppet/util/network_device/transport/telnet.rb" -/bin/rm -Rf "${3}/puppet/face/help/action.erb" +/bin/rm -Rf "${3}/puppet/util/network_device/transport/base.rb" -/bin/rm -Rf "${3}/puppet/face/help/face.erb" +/bin/rm -Rf "${3}/puppet/util/network_device/transport/ssh.rb" -/bin/rm -Rf "${3}/puppet/face/help/man.erb" +/bin/rm -Rf "${3}/puppet/util/network_device/base.rb" -/bin/rm -Rf "${3}/puppet/face/help/global.erb" +/bin/rm -Rf "${3}/puppet/util/monkey_patches.rb" -/bin/rm -Rf "${3}/puppet/face/man.rb" +/bin/rm -Rf "${3}/puppet/util/warnings.rb" -/bin/rm -Rf "${3}/puppet/face/certificate_request.rb" +/bin/rm -Rf "${3}/puppet/util/execution.rb" -/bin/rm -Rf "${3}/puppet/face/module.rb" +/bin/rm -Rf "${3}/puppet/util/instance_loader.rb" -/bin/rm -Rf "${3}/puppet/face/instrumentation_listener.rb" +/bin/rm -Rf "${3}/puppet/util/platform.rb" -/bin/rm -Rf "${3}/puppet/face/node.rb" +/bin/rm -Rf "${3}/puppet/util/log.rb" -/bin/rm -Rf "${3}/puppet/face/resource.rb" +/bin/rm -Rf "${3}/puppet/util/feature.rb" -/bin/rm -Rf "${3}/puppet/face/certificate.rb" +/bin/rm -Rf "${3}/puppet/util/provider_features.rb" -/bin/rm -Rf "${3}/puppet/face/file.rb" +/bin/rm -Rf "${3}/puppet/util/command_line.rb" -/bin/rm -Rf "${3}/puppet/face/key.rb" +/bin/rm -Rf "${3}/puppet/util/autoload/file_cache.rb" -/bin/rm -Rf "${3}/puppet/face/file/store.rb" +/bin/rm -Rf "${3}/puppet/util/fileparsing.rb" -/bin/rm -Rf "${3}/puppet/face/file/download.rb" +/bin/rm -Rf "${3}/puppet/util/backups.rb" -/bin/rm -Rf "${3}/puppet/face/facts.rb" +/bin/rm -Rf "${3}/puppet/util/posix.rb" -/bin/rm -Rf "${3}/puppet/face/catalog/select.rb" +/bin/rm -Rf "${3}/puppet/util/rails/reference_serializer.rb" -/bin/rm -Rf "${3}/puppet/face/config.rb" +/bin/rm -Rf "${3}/puppet/util/rails/collection_merger.rb" -/bin/rm -Rf "${3}/puppet/face/ca.rb" +/bin/rm -Rf "${3}/puppet/util/rails/cache_accumulator.rb" -/bin/rm -Rf "${3}/puppet/face/help.rb" +/bin/rm -Rf "${3}/puppet/util/pson.rb" -/bin/rm -Rf "${3}/puppet/face/module/upgrade.rb" +/bin/rm -Rf "${3}/puppet/util/settings/boolean_setting.rb" -/bin/rm -Rf "${3}/puppet/face/module/install.rb" +/bin/rm -Rf "${3}/puppet/util/settings/file_setting.rb" -/bin/rm -Rf "${3}/puppet/face/module/search.rb" +/bin/rm -Rf "${3}/puppet/util/settings/setting.rb" -/bin/rm -Rf "${3}/puppet/face/module/build.rb" +/bin/rm -Rf "${3}/puppet/util/symbolic_file_mode.rb" -/bin/rm -Rf "${3}/puppet/face/module/changes.rb" +/bin/rm -Rf "${3}/puppet/util/selinux.rb" -/bin/rm -Rf "${3}/puppet/face/module/list.rb" +/bin/rm -Rf "${3}/puppet/util/resource_template.rb" -/bin/rm -Rf "${3}/puppet/face/module/generate.rb" +/bin/rm -Rf "${3}/puppet/util/log_paths.rb" -/bin/rm -Rf "${3}/puppet/face/module/uninstall.rb" +/bin/rm -Rf "${3}/puppet/util/windows.rb" -/bin/rm -Rf "${3}/puppet/face/plugin.rb" +/bin/rm -Rf "${3}/puppet/util/file_locking.rb" -/bin/rm -Rf "${3}/puppet/face/parser.rb" +/bin/rm -Rf "${3}/puppet/util/classgen.rb" -/bin/rm -Rf "${3}/puppet/face/certificate_revocation_list.rb" +/bin/rm -Rf "${3}/puppet/util/instrumentation.rb" -/bin/rm -Rf "${3}/puppet/face/status.rb" +/bin/rm -Rf "${3}/puppet/util/rdoc/generators/puppet_generator.rb" -/bin/rm -Rf "${3}/puppet/face/secret_agent.rb" +/bin/rm -Rf "${3}/puppet/util/rdoc/generators/template/puppet/puppet.rb" -/bin/rm -Rf "${3}/puppet/face/report.rb" +/bin/rm -Rf "${3}/puppet/util/rdoc/parser.rb" -/bin/rm -Rf "${3}/puppet/face/instrumentation_probe.rb" +/bin/rm -Rf "${3}/puppet/util/rdoc/code_objects.rb" -/bin/rm -Rf "${3}/puppet/face/node/clean.rb" +/bin/rm -Rf "${3}/puppet/util/colors.rb" -/bin/rm -Rf "${3}/puppet/face/instrumentation_data.rb" +/bin/rm -Rf "${3}/puppet/util/inifile.rb" -/bin/rm -Rf "${3}/puppet/face/resource_type.rb" +/bin/rm -Rf "${3}/puppet/util/nagios_maker.rb" -/bin/rm -Rf "${3}/puppet/property/keyvalue.rb" +/bin/rm -Rf "${3}/puppet/util/package.rb" -/bin/rm -Rf "${3}/puppet/property/ordered_list.rb" +/bin/rm -Rf "${3}/puppet/util/reference.rb" -/bin/rm -Rf "${3}/puppet/property/list.rb" +/bin/rm -Rf "${3}/puppet/file_serving/content.rb" -/bin/rm -Rf "${3}/puppet/property/ensure.rb" +/bin/rm -Rf "${3}/puppet/file_serving/metadata.rb" -/bin/rm -Rf "${3}/puppet/configurer/plugin_handler.rb" +/bin/rm -Rf "${3}/puppet/file_serving/mount.rb" -/bin/rm -Rf "${3}/puppet/configurer/downloader.rb" +/bin/rm -Rf "${3}/puppet/file_serving/configuration/parser.rb" -/bin/rm -Rf "${3}/puppet/configurer/fact_handler.rb" +/bin/rm -Rf "${3}/puppet/file_serving/fileset.rb" -/bin/rm -Rf "${3}/puppet/status.rb" +/bin/rm -Rf "${3}/puppet/file_serving/terminus_selector.rb" -/bin/rm -Rf "${3}/puppet/network.rb" +/bin/rm -Rf "${3}/puppet/file_serving/terminus_helper.rb" -/bin/rm -Rf "${3}/puppet/module_tool.rb" +/bin/rm -Rf "${3}/puppet/file_serving/base.rb" -/bin/rm -Rf "${3}/puppet/simple_graph.rb" +/bin/rm -Rf "${3}/puppet/file_serving/mount/plugins.rb" -/bin/rm -Rf "${3}/puppet/rails.rb" +/bin/rm -Rf "${3}/puppet/file_serving/mount/file.rb" -/bin/rm -Rf "${3}/puppet/rails/source_file.rb" +/bin/rm -Rf "${3}/puppet/file_serving/mount/modules.rb" -/bin/rm -Rf "${3}/puppet/rails/resource_tag.rb" +/bin/rm -Rf "${3}/puppet/file_serving/configuration.rb" -/bin/rm -Rf "${3}/puppet/rails/fact_name.rb" +/bin/rm -Rf "${3}/puppet/rails/resource.rb" /bin/rm -Rf "${3}/puppet/rails/puppet_tag.rb" /bin/rm -Rf "${3}/puppet/rails/database/001_add_created_at_to_all_tables.rb" -/bin/rm -Rf "${3}/puppet/rails/database/003_add_environment_to_host.rb" +/bin/rm -Rf "${3}/puppet/rails/database/schema.rb" /bin/rm -Rf "${3}/puppet/rails/database/002_remove_duplicated_index_on_all_tables.rb" -/bin/rm -Rf "${3}/puppet/rails/database/schema.rb" - /bin/rm -Rf "${3}/puppet/rails/database/004_add_inventory_service_tables.rb" -/bin/rm -Rf "${3}/puppet/rails/inventory_node.rb" +/bin/rm -Rf "${3}/puppet/rails/database/003_add_environment_to_host.rb" -/bin/rm -Rf "${3}/puppet/rails/resource.rb" +/bin/rm -Rf "${3}/puppet/rails/resource_tag.rb" -/bin/rm -Rf "${3}/puppet/rails/param_name.rb" +/bin/rm -Rf "${3}/puppet/rails/inventory_fact.rb" -/bin/rm -Rf "${3}/puppet/rails/benchmark.rb" +/bin/rm -Rf "${3}/puppet/rails/param_value.rb" -/bin/rm -Rf "${3}/puppet/rails/host.rb" +/bin/rm -Rf "${3}/puppet/rails/fact_name.rb" -/bin/rm -Rf "${3}/puppet/rails/param_value.rb" +/bin/rm -Rf "${3}/puppet/rails/host.rb" -/bin/rm -Rf "${3}/puppet/rails/inventory_fact.rb" +/bin/rm -Rf "${3}/puppet/rails/source_file.rb" /bin/rm -Rf "${3}/puppet/rails/fact_value.rb" -/bin/rm -Rf "${3}/puppet/property.rb" +/bin/rm -Rf "${3}/puppet/rails/benchmark.rb" -/bin/rm -Rf "${3}/puppet/resource/catalog.rb" +/bin/rm -Rf "${3}/puppet/rails/inventory_node.rb" -/bin/rm -Rf "${3}/puppet/resource/type.rb" +/bin/rm -Rf "${3}/puppet/rails/param_name.rb" -/bin/rm -Rf "${3}/puppet/resource/status.rb" +/bin/rm -Rf "${3}/puppet/external/nagios.rb" -/bin/rm -Rf "${3}/puppet/resource/type_collection.rb" +/bin/rm -Rf "${3}/puppet/external/dot.rb" -/bin/rm -Rf "${3}/puppet/resource/type_collection_helper.rb" +/bin/rm -Rf "${3}/puppet/external/nagios/grammar.ry" -/bin/rm -Rf "${3}/puppet/node/environment.rb" +/bin/rm -Rf "${3}/puppet/external/nagios/parser.rb" -/bin/rm -Rf "${3}/puppet/node/inventory.rb" +/bin/rm -Rf "${3}/puppet/external/nagios/base.rb" -/bin/rm -Rf "${3}/puppet/node/facts.rb" +/bin/rm -Rf "${3}/puppet/external/nagios/makefile" -/bin/rm -Rf "${3}/puppet/parameter/value.rb" +/bin/rm -Rf "${3}/puppet/external/lock.rb" + +/bin/rm -Rf "${3}/puppet/external/pson/version.rb" + +/bin/rm -Rf "${3}/puppet/external/pson/pure.rb" + +/bin/rm -Rf "${3}/puppet/external/pson/pure/generator.rb" + +/bin/rm -Rf "${3}/puppet/external/pson/pure/parser.rb" + +/bin/rm -Rf "${3}/puppet/external/pson/common.rb" + +/bin/rm -Rf "${3}/puppet/external/base64.rb" /bin/rm -Rf "${3}/puppet/parameter/value_collection.rb" +/bin/rm -Rf "${3}/puppet/parameter/value.rb" + /bin/rm -Rf "${3}/puppet/parameter/path.rb" -/bin/rm -Rf "${3}/puppet/transaction.rb" +/bin/rm -Rf "${3}/puppet/reports.rb" -/bin/rm -Rf "${3}/semver.rb" +/bin/rm -Rf "${3}/puppet/interface.rb" +/bin/rm -Rf "${3}/puppet/network/format.rb" + +/bin/rm -Rf "${3}/puppet/network/authstore.rb" +/bin/rm -Rf "${3}/puppet/network/rest_authorization.rb" +/bin/rm -Rf "${3}/puppet/network/authorization.rb" -/bin/rm -Rf "${3}/pi" +/bin/rm -Rf "${3}/puppet/network/handler/ca.rb" -/bin/rm -Rf "${3}/filebucket" +/bin/rm -Rf "${3}/puppet/network/handler/fileserver.rb" + +/bin/rm -Rf "${3}/puppet/network/handler/status.rb" + +/bin/rm -Rf "${3}/puppet/network/handler/filebucket.rb" + +/bin/rm -Rf "${3}/puppet/network/handler/runner.rb" + +/bin/rm -Rf "${3}/puppet/network/handler/report.rb" + +/bin/rm -Rf "${3}/puppet/network/handler/master.rb" + +/bin/rm -Rf "${3}/puppet/network/http_pool.rb" + +/bin/rm -Rf "${3}/puppet/network/http_server/mongrel.rb" + +/bin/rm -Rf "${3}/puppet/network/xmlrpc/server.rb" + +/bin/rm -Rf "${3}/puppet/network/xmlrpc/processor.rb" + +/bin/rm -Rf "${3}/puppet/network/xmlrpc/webrick_servlet.rb" + +/bin/rm -Rf "${3}/puppet/network/rest_controller.rb" + +/bin/rm -Rf "${3}/puppet/network/client_request.rb" + +/bin/rm -Rf "${3}/puppet/network/rest_authconfig.rb" + +/bin/rm -Rf "${3}/puppet/network/server.rb" + +/bin/rm -Rf "${3}/puppet/network/handler.rb" + +/bin/rm -Rf "${3}/puppet/network/formats.rb" + +/bin/rm -Rf "${3}/puppet/network/http/webrick/rest.rb" + +/bin/rm -Rf "${3}/puppet/network/http/mongrel.rb" + +/bin/rm -Rf "${3}/puppet/network/http/handler.rb" + +/bin/rm -Rf "${3}/puppet/network/http/compression.rb" + +/bin/rm -Rf "${3}/puppet/network/http/mongrel/rest.rb" + +/bin/rm -Rf "${3}/puppet/network/http/api/v1.rb" + +/bin/rm -Rf "${3}/puppet/network/http/api.rb" + +/bin/rm -Rf "${3}/puppet/network/http/rack/httphandler.rb" + +/bin/rm -Rf "${3}/puppet/network/http/rack/rest.rb" + +/bin/rm -Rf "${3}/puppet/network/http/rack/xmlrpc.rb" + +/bin/rm -Rf "${3}/puppet/network/http/webrick.rb" + +/bin/rm -Rf "${3}/puppet/network/http/rack.rb" + +/bin/rm -Rf "${3}/puppet/network/authconfig.rb" + +/bin/rm -Rf "${3}/puppet/network/http_server.rb" + +/bin/rm -Rf "${3}/puppet/network/format_handler.rb" + +/bin/rm -Rf "${3}/puppet/network/rights.rb" + +/bin/rm -Rf "${3}/puppet/network/http.rb" + +/bin/rm -Rf "${3}/puppet/rails.rb" + +/bin/rm -Rf "${3}/puppet/metatype/manager.rb" + +/bin/rm -Rf "${3}/puppet/provider.rb" + +/bin/rm -Rf "${3}/puppet.rb" + + + + +/bin/rm -Rf "${3}/pi" /bin/rm -Rf "${3}/ralsh" +/bin/rm -Rf "${3}/puppetdoc" + /bin/rm -Rf "${3}/puppet" -/bin/rm -Rf "${3}/puppetdoc" +/bin/rm -Rf "${3}/filebucket" diff --git a/ext/osx/prototype.plist b/ext/osx/prototype.plist index 7ff1ab837..32e7c431f 100644 --- a/ext/osx/prototype.plist +++ b/ext/osx/prototype.plist @@ -5,13 +5,13 @@ <key>CFBundleIdentifier</key> <string></string> <key>CFBundleShortVersionString</key> - <string>2.7.21</string> + <string>2.7.23</string> <key>IFMajorVersion</key> <integer></integer> <key>IFMinorVersion</key> <integer></integer> <key>IFPkgBuildDate</key> - <date></date> + <date>2013-08-14-14-39-37</date> <key>IFPkgFlagAllowBackRev</key> <false/> <key>IFPkgFlagAuthorizationAction</key> diff --git a/ext/redhat/puppet.spec b/ext/redhat/puppet.spec index 00e836305..7eb4cb6a2 100644 --- a/ext/redhat/puppet.spec +++ b/ext/redhat/puppet.spec @@ -10,8 +10,8 @@ %endif # VERSION is subbed out during rake srpm process -# %global realversion 2.7.21 -# %global rpmversion 2.7.21 +# %global realversion 2.7.23 +# %global rpmversion 2.7.23 %global confdir conf/redhat @@ -303,8 +303,8 @@ fi rm -rf %{buildroot} %changelog -* Mon Mar 11 2013 Puppet Labs Release <info@puppetlabs.com> - 2.7.21-1 -- Build for 2.7.21 +* Wed Aug 14 2013 Puppet Labs Release <info@puppetlabs.com> - 2.7.23-1 +- Build for 2.7.23 * Tue Oct 30 2012 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.19-1.0 - Remove the asc file as a source since it was never used diff --git a/install.rb b/install.rb index c77edff88..e0280f128 100755 --- a/install.rb +++ b/install.rb @@ -121,7 +121,7 @@ end def do_libs(libs, strip = 'lib/') libs.each do |lf| - olf = File.join(InstallOptions.site_dir, lf.gsub(/#{strip}/, '')) + olf = File.join(InstallOptions.site_dir, lf.sub(/^#{strip}/, '')) op = File.dirname(olf) if $haveftools File.makedirs(op, true) diff --git a/lib/puppet.rb b/lib/puppet.rb index 1596c41c5..771fb24b5 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -7,6 +7,8 @@ rescue LoadError end # see the bottom of the file for further inclusions +# Also see the new Vendor support - towards the end + require 'singleton' require 'facter' require 'puppet/error' @@ -26,6 +28,8 @@ require 'puppet/util/run_mode' # it's also a place to find top-level commands like 'debug' module Puppet + require 'puppet/file_system' + class << self include Puppet::Util attr_reader :features @@ -112,6 +116,15 @@ module Puppet def self.newtype(name, options = {}, &block) Puppet::Type.newtype(name, options, &block) end + + # Load vendored (setup paths, and load what is needed upfront). + # See the Vendor class for how to add additional vendored gems/code + require "puppet/vendor" + Puppet::Vendor.load_vendored + + # Set default for YAML.load to unsafe so we don't affect programs + # requiring puppet -- in puppet we will call safe explicitly + SafeYAML::OPTIONS[:default_mode] = :unsafe end require 'puppet/type' diff --git a/lib/puppet/file_system.rb b/lib/puppet/file_system.rb new file mode 100644 index 000000000..d9e5b8fd3 --- /dev/null +++ b/lib/puppet/file_system.rb @@ -0,0 +1,3 @@ +module Puppet::FileSystem + require 'puppet/file_system/path_pattern' +end diff --git a/lib/puppet/file_system/path_pattern.rb b/lib/puppet/file_system/path_pattern.rb new file mode 100644 index 000000000..b6d7925c4 --- /dev/null +++ b/lib/puppet/file_system/path_pattern.rb @@ -0,0 +1,97 @@ +require 'pathname' + +module Puppet::FileSystem + class PathPattern + class InvalidPattern < Puppet::Error; end + + TRAVERSAL = /^\.\.$/ + ABSOLUTE_UNIX = /^\// + ABSOLUTE_WINDOWS = /^[a-z]:/i + #ABSOLUT_VODKA #notappearinginthisclass + CURRENT_DRIVE_RELATIVE_WINDOWS = /^\\/ + + def self.relative(pattern) + RelativePathPattern.new(pattern) + end + + def self.absolute(pattern) + AbsolutePathPattern.new(pattern) + end + + class << self + protected :new + end + + # @param prefix [AbsolutePathPattern] An absolute path pattern instance + # @return [AbsolutePathPattern] A new AbsolutePathPattern prepended with + # the passed prefix's pattern. + def prefix_with(prefix) + new_pathname = prefix.pathname + pathname + self.class.absolute(new_pathname.to_s) + end + + def glob + Dir.glob(pathname.to_s) + end + + def to_s + pathname.to_s + end + + protected + + attr_reader :pathname + + private + + def validate + @pathname.each_filename do |e| + if e =~ TRAVERSAL + raise(InvalidPattern, "PathPatterns cannot be created with directory traversals.") + end + end + case @pathname.to_s + when CURRENT_DRIVE_RELATIVE_WINDOWS + raise(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.") + end + end + + def initialize(pattern) + begin + @pathname = Pathname.new(pattern.strip) + rescue ArgumentError => error + raise InvalidPattern.new("PathPatterns cannot be created with a zero byte.", error) + end + validate + end + end + + class RelativePathPattern < PathPattern + def absolute? + false + end + + def validate + super + case @pathname.to_s + when ABSOLUTE_WINDOWS + raise(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.") + when ABSOLUTE_UNIX + raise(InvalidPattern, "A relative PathPattern cannot be an absolute path.") + end + end + end + + class AbsolutePathPattern < PathPattern + def absolute? + true + end + + def validate + super + if @pathname.to_s !~ ABSOLUTE_UNIX and @pathname.to_s !~ ABSOLUTE_WINDOWS + raise(InvalidPattern, "An absolute PathPattern cannot be a relative path.") + end + end + end +end diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb index dfda0f6ce..e79c18473 100644 --- a/lib/puppet/indirector/report/processor.rb +++ b/lib/puppet/indirector/report/processor.rb @@ -49,7 +49,7 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code end def processors(&blk) - return if Puppet[:reports] == "none" + return [] if Puppet[:reports] == "none" reports.each do |name| if mod = Puppet::Reports.report(name) yield(mod) diff --git a/lib/puppet/indirector/report/rest.rb b/lib/puppet/indirector/report/rest.rb index 601da9edb..6febdb869 100644 --- a/lib/puppet/indirector/report/rest.rb +++ b/lib/puppet/indirector/report/rest.rb @@ -4,4 +4,11 @@ class Puppet::Transaction::Report::Rest < Puppet::Indirector::REST desc "Get server report over HTTP via REST." use_server_setting(:report_server) use_port_setting(:report_port) + + private + + def deserialize_save(content_type, body) + format = Puppet::Network::FormatHandler.protected_format(content_type) + format.intern(Array, body) + end end diff --git a/lib/puppet/indirector/resource/rest.rb b/lib/puppet/indirector/resource/rest.rb index 7848ae65e..b9cae86a3 100644 --- a/lib/puppet/indirector/resource/rest.rb +++ b/lib/puppet/indirector/resource/rest.rb @@ -2,4 +2,13 @@ require 'puppet/indirector/status' require 'puppet/indirector/rest' class Puppet::Resource::Rest < Puppet::Indirector::REST + + private + + def deserialize_save(content_type, body) + # Body is [ral_res.to_resource, transaction.report] + format = Puppet::Network::FormatHandler.protected_format(content_type) + ary = format.intern(Array, body) + [Puppet::Resource.from_pson(ary[0]), Puppet::Transaction::Report.from_pson(ary[1])] + end end diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 02053e18d..818c23ef8 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -32,36 +32,6 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus Puppet.settings[port_setting || :masterport].to_i end - # Figure out the content type, turn that into a format, and use the format - # to extract the body of the response. - def deserialize(response, multiple = false) - case response.code - when "404" - return nil - when /^2/ - raise "No content type in http response; cannot parse" unless response['content-type'] - - content_type = response['content-type'].gsub(/\s*;.*$/,'') # strip any appended charset - - body = uncompress_body(response) - - # Convert the response to a deserialized object. - if multiple - model.convert_from_multiple(content_type, body) - else - model.convert_from(content_type, body) - end - else - # Raise the http error if we didn't get a 'success' of some kind. - raise convert_to_http_error(response) - end - end - - def convert_to_http_error(response) - message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}" - Net::HTTPError.new(message, response) - end - # Provide appropriate headers. def headers add_accept_encoding({"Accept" => model.supported_formats.join(", ")}) @@ -127,39 +97,58 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus else http_get(request, uri_with_query_string, headers) end - result = deserialize response - result.name = request.key if result.respond_to?(:name=) - result + + if is_http_200?(response) + content_type, body = parse_response(response) + result = deserialize_find(content_type, body) + result.name = request.key if result.respond_to?(:name=) + result + else + nil + end end def head(request) response = http_head(request, indirection2uri(request), headers) - case response.code - when "404" - return false - when /^2/ - return true - else - # Raise the http error if we didn't get a 'success' of some kind. - raise convert_to_http_error(response) - end + + !!is_http_200?(response) end def search(request) - unless result = deserialize(http_get(request, indirection2uri(request), headers), true) - return [] + response = http_get(request, indirection2uri(request), headers) + + if is_http_200?(response) + content_type, body = parse_response(response) + deserialize_search(content_type, body) || [] + else + [] end - result end def destroy(request) raise ArgumentError, "DELETE does not accept options" unless request.options.empty? - deserialize http_delete(request, indirection2uri(request), headers) + + response = http_delete(request, indirection2uri(request), headers) + + if is_http_200?(response) + content_type, body = parse_response(response) + deserialize_destroy(content_type, body) + else + nil + end end def save(request) raise ArgumentError, "PUT does not accept options" unless request.options.empty? - deserialize http_put(request, indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime })) + + response = http_put(request, indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime })) + + if is_http_200?(response) + content_type, body = parse_response(response) + deserialize_save(content_type, body) + else + nil + end end def validate_key(request) @@ -168,6 +157,51 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus private + def is_http_200?(response) + case response.code + when "404" + false + when /^2/ + true + else + # Raise the http error if we didn't get a 'success' of some kind. + raise convert_to_http_error(response) + end + end + + def convert_to_http_error(response) + message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}" + Net::HTTPError.new(message, response) + end + + # Returns the content_type, stripping any appended charset, and the + # body, decompressed if necessary (content-encoding is checked inside + # uncompress_body) + def parse_response(response) + if response['content-type'] + [ response['content-type'].gsub(/\s*;.*$/,''), + body = uncompress_body(response) ] + else + raise "No content type in http response; cannot parse" + end + end + + def deserialize_find(content_type, body) + model.convert_from(content_type, body) + end + + def deserialize_search(content_type, body) + model.convert_from_multiple(content_type, body) + end + + def deserialize_destroy(content_type, body) + model.convert_from(content_type, body) + end + + def deserialize_save(content_type, body) + nil + end + def environment Puppet::Node::Environment.new end diff --git a/lib/puppet/indirector/run/rest.rb b/lib/puppet/indirector/run/rest.rb index cbd34814a..f857d45fe 100644 --- a/lib/puppet/indirector/run/rest.rb +++ b/lib/puppet/indirector/run/rest.rb @@ -3,4 +3,10 @@ require 'puppet/indirector/rest' class Puppet::Run::Rest < Puppet::Indirector::REST desc "Trigger Agent runs via REST." + + private + + def deserialize_save(content_type, body) + model.convert_from(content_type, body) + end end diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb index 04319cc18..510f539f9 100644 --- a/lib/puppet/module.rb +++ b/lib/puppet/module.rb @@ -11,6 +11,7 @@ class Puppet::Module class IncompatiblePlatform < Error; end class MissingMetadata < Error; end class InvalidName < Error; end + class InvalidFilePattern < Error; end include Puppet::Util::Logging @@ -138,10 +139,16 @@ class Puppet::Module # Return the list of manifests matching the given glob pattern, # defaulting to 'init.{pp,rb}' for empty modules. def match_manifests(rest) - pat = File.join(path, MANIFESTS, rest || 'init') - [manifest("init.pp"),manifest("init.rb")].compact + Dir. - glob(pat + (File.extname(pat).empty? ? '.{pp,rb}' : '')). - reject { |f| FileTest.directory?(f) } + if rest + wanted_manifests = wanted_manifests_from(rest) + searched_manifests = wanted_manifests.glob.reject { |f| FileTest.directory?(f) } + else + searched_manifests = [] + end + + # (#4220) Always ensure init.pp in case class is defined there. + init_manifests = [manifest("init.pp"), manifest("init.rb")].compact + init_manifests + searched_manifests end def metadata_file @@ -286,6 +293,20 @@ class Puppet::Module private + def wanted_manifests_from(pattern) + begin + extended = File.extname(pattern).empty? ? "#{pattern}.{pp,rb}" : pattern + relative_pattern = Puppet::FileSystem::PathPattern.relative(extended) + rescue Puppet::FileSystem::PathPattern::InvalidPattern => error + raise Puppet::Module::InvalidFilePattern.new( + "The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " + + "is invalid and potentially unsafe.", error) + end + + absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(subpath(MANIFESTS)) + relative_pattern.prefix_with(absolute_path_to_manifests) + end + def subpath(type) return File.join(path, type) unless type.to_s == "plugins" diff --git a/lib/puppet/module_tool/applications/unpacker.rb b/lib/puppet/module_tool/applications/unpacker.rb index 3ed6058f3..cca625fcb 100644 --- a/lib/puppet/module_tool/applications/unpacker.rb +++ b/lib/puppet/module_tool/applications/unpacker.rb @@ -9,7 +9,8 @@ module Puppet::ModuleTool @filename = Pathname.new(filename) parsed = parse_filename(filename) super(options) - @module_dir = Pathname.new(options[:target_dir]) + parsed[:dir_name] + @module_path = Pathname(options[:target_dir]) + @module_dir = @module_path + parsed[:dir_name] end def run @@ -46,6 +47,9 @@ module Puppet::ModuleTool else Puppet::Util.execute("tar xzf #{@filename} -C #{build_dir}") end + Puppet::Util.execute("find #{build_dir} -type d -exec chmod 755 {} +") + Puppet::Util.execute("find #{build_dir} -type f -exec chmod 644 {} +") + Puppet::Util.execute("chown -R #{@module_path.stat.uid}:#{@module_path.stat.gid} #{build_dir}") rescue Puppet::ExecutionFailure => e raise RuntimeError, "Could not extract contents of module archive: #{e.message}" end diff --git a/lib/puppet/network/formats.rb b/lib/puppet/network/formats.rb index 79fc5ca6d..49bd5f598 100644 --- a/lib/puppet/network/formats.rb +++ b/lib/puppet/network/formats.rb @@ -3,12 +3,20 @@ require 'puppet/network/format_handler' Puppet::Network::FormatHandler.create_serialized_formats(:yaml) do # Yaml doesn't need the class name; it's serialized. def intern(klass, text) - YAML.safely_load(text) + data = YAML.load(text, :safe => true, :deserialize_symbols => true) + return data if data.is_a?(klass) + klass.from_pson(data) end # Yaml doesn't need the class name; it's serialized. def intern_multiple(klass, text) - YAML.safely_load(text) + YAML.load(text, :safe => true, :deserialize_symbols => true).collect do |data| + if data.is_a?(klass) + data + else + klass.from_pson(data) + end + end end def render(instance) @@ -45,11 +53,15 @@ Puppet::Network::FormatHandler.create_serialized_formats(:b64_zlib_yaml) do end def intern(klass, text) - decode(text) + requiring_zlib do + Puppet::Network::FormatHandler.format(:yaml).intern(klass, decode(text)) + end end def intern_multiple(klass, text) - decode(text) + requiring_zlib do + Puppet::Network::FormatHandler.format(:yaml).intern_multiple(klass, decode(text)) + end end def render(instance) @@ -64,15 +76,13 @@ Puppet::Network::FormatHandler.create_serialized_formats(:b64_zlib_yaml) do true end - def encode(text) - requiring_zlib do - Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION)) - end + def decode(data) + Zlib::Inflate.inflate(Base64.decode64(data)) end - def decode(yaml) + def encode(text) requiring_zlib do - YAML.safely_load(Zlib::Inflate.inflate(Base64.decode64(yaml))) + Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION)) end end end diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb index 756fa163b..8fba2706c 100644 --- a/lib/puppet/network/http/handler.rb +++ b/lib/puppet/network/http/handler.rb @@ -239,7 +239,7 @@ module Puppet::Network::HTTP::Handler next result if param == :ip value = CGI.unescape(value) if value =~ /^---/ - value = YAML.safely_load(value) + value = YAML.load(value, :safe => true, :deserialize_symbols => true) else value = true if value == "true" value = false if value == "false" diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb index 5b0a98615..f63b68b47 100644 --- a/lib/puppet/node.rb +++ b/lib/puppet/node.rb @@ -20,6 +20,31 @@ class Puppet::Node attr_accessor :name, :classes, :source, :ipaddress, :parameters attr_reader :time + ::PSON.register_document_type('Node',self) + + def self.from_pson(pson) + raise ArgumentError, "No name provided in serialized data" unless name = pson['name'] + + node = new(name) + node.classes = pson['classes'] + node.parameters = pson['parameters'] + node.environment = pson['environment'] + node + end + + def to_pson(*args) + result = { + 'document_type' => "Node", + 'data' => {} + } + result['data']['name'] = name + result['data']['classes'] = classes unless classes.empty? + result['data']['parameters'] = parameters unless parameters.empty? + result['data']['environment'] = environment.name + + result.to_pson(*args) + end + def environment return super if @environment diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb index 577b62b62..4906523f6 100755 --- a/lib/puppet/node/facts.rb +++ b/lib/puppet/node/facts.rb @@ -47,6 +47,26 @@ class Puppet::Node::Facts end end + def initialize_from_hash(data) + @name = data['name'] + @values = data['values'] + # Timestamp will be here in YAML + timestamp = data['values']['_timestamp'] + @values.delete_if do |key, val| + key =~ /^_/ + end + + #Timestamp will be here in pson + timestamp ||= data['timestamp'] + timestamp = Time.parse(timestamp) if timestamp.is_a? String + self.timestamp = timestamp + + self.expiration = data['expiration'] + if expiration.is_a? String + self.expiration = Time.parse(expiration) + end + end + # Convert all fact values into strings. def stringify values.each do |fact, value| @@ -60,10 +80,9 @@ class Puppet::Node::Facts end def self.from_pson(data) - result = new(data['name'], data['values']) - result.timestamp = Time.parse(data['timestamp']) - result.expiration = Time.parse(data['expiration']) - result + new_facts = allocate + new_facts.initialize_from_hash(data) + new_facts end def to_pson(*args) diff --git a/lib/puppet/parser/files.rb b/lib/puppet/parser/files.rb index 78fdf0314..731c76a43 100644 --- a/lib/puppet/parser/files.rb +++ b/lib/puppet/parser/files.rb @@ -8,23 +8,25 @@ require 'puppet/parser/parser' module Puppet::Parser::Files module_function - # Return a list of manifests (as absolute filenames) that match +pat+ - # with the current directory set to +cwd+. If the first component of - # +pat+ does not contain any wildcards and is an existing module, return - # a list of manifests in that module matching the rest of +pat+ - # Otherwise, try to find manifests matching +pat+ relative to +cwd+ - def find_manifests(start, options = {}) - cwd = options[:cwd] || Dir.getwd - module_name, pattern = split_file_path(start) + # Return a list of manifests as absolute filenames matching the given + # pattern. + # + # @param pattern [String] A reference for a file in a module. It is the format "<modulename>/<file glob>" + # @param environment [Puppet::Node::Environment] the environment of modules + # + # @return [Array(String, Array<String>)] the module name and the list of files found + # @api private + def find_manifests_in_modules(pattern, environment) + module_name, file_pattern = split_file_path(pattern) begin - if mod = Puppet::Module.find(module_name, options[:environment]) - return [mod.name, mod.match_manifests(pattern)] + if mod = Puppet::Module.find(module_name, environment) + return [mod.name, mod.match_manifests(file_pattern)] end rescue Puppet::Module::InvalidName - # Than that would be a "no." + # one of the modules being loaded might have an invalid name and so + # looking for one might blow up since we load them lazily. end - abspat = File::expand_path(start, cwd) - [nil, Dir.glob(abspat + (File.extname(abspat).empty? ? '{.pp,.rb}' : '' )).uniq.reject { |f| FileTest.directory?(f) }] + [nil, []] end # Find the concrete file denoted by +file+. If +file+ is absolute, @@ -80,9 +82,12 @@ module Puppet::Parser::Files # Split the path into the module and the rest of the path, or return # nil if the path is empty or absolute (starts with a /). - # This method can return nil & anyone calling it needs to handle that. def split_file_path(path) - path.split(File::SEPARATOR, 2) unless path == "" or Puppet::Util.absolute_path?(path) + if path == "" or Puppet::Util.absolute_path?(path) + nil + else + path.split(File::SEPARATOR, 2) + end end end diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index 7888fe1dc..87b2e9daf 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -101,7 +101,16 @@ class Puppet::Parser::Parser end def import(file) - known_resource_types.loader.import(file, @lexer.file) + if @lexer.file + # use a path relative to the file doing the importing + dir = File.dirname(@lexer.file) + else + # otherwise assume that everything needs to be from where the user is + # executing this command. Normally, this would be in a "puppet apply -e" + dir = Dir.pwd + end + + known_resource_types.loader.import(file, dir) end def initialize(env) diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb index 861a098a5..17f18a698 100644 --- a/lib/puppet/parser/type_loader.rb +++ b/lib/puppet/parser/type_loader.rb @@ -59,40 +59,34 @@ class Puppet::Parser::TypeLoader end end - # Import our files. - def import(file, current_file = nil) + # Import manifest files that match a given file glob pattern. + # + # @param pattern [String] the file glob to apply when determining which files + # to load + # @param dir [String] base directory to use when the file is not + # found in a module + # @api private + def import(pattern, dir) return if Puppet[:ignoreimport] - # use a path relative to the file doing the importing - if current_file - dir = current_file.sub(%r{[^/]+$},'').sub(/\/$/, '') - else - dir = "." - end - if dir == "" - dir = "." - end + modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment) + if files.empty? + abspat = File.expand_path(pattern, dir) + file_pattern = abspat + (File.extname(abspat).empty? ? '{.pp,.rb}' : '' ) - pat = file - modname, files = Puppet::Parser::Files.find_manifests(pat, :cwd => dir, :environment => environment) - if files.size == 0 - raise Puppet::ImportError.new("No file(s) found for import of '#{pat}'") - end + files = Dir.glob(file_pattern).uniq.reject { |f| FileTest.directory?(f) } + modname = nil - loaded_asts = [] - files.each do |file| - unless Puppet::Util.absolute_path?(file) - file = File.join(dir, file) + if files.empty? + raise_no_files_found(pattern) end - @loading_helper.do_once(file) do - loaded_asts << parse_file(file) - end - end - loaded_asts.inject([]) do |loaded_types, ast| - loaded_types + known_resource_types.import_ast(ast, modname) end + + load_files(modname, files) end + # Load all of the manifest files in all known modules. + # @api private def import_all module_names = [] # Collect the list of all known modules @@ -113,7 +107,7 @@ class Puppet::Parser::TypeLoader mod = Puppet::Module.new(name, :environment => environment) Find.find(File.join(mod.path, "manifests")) do |path| if path =~ /\.pp$/ or path =~ /\.rb$/ - import(path) + load_files(mod.name, [path]) end end end @@ -133,7 +127,7 @@ class Puppet::Parser::TypeLoader return nil if fqname == "" # special-case main. name2files(fqname).each do |filename| begin - imported_types = import(filename) + imported_types = import_from_modules(filename) if result = imported_types.find { |t| t.type == type and t.name == fqname } Puppet.debug "Automatically imported #{fqname} from #{filename} into #{environment}" return result @@ -157,6 +151,32 @@ class Puppet::Parser::TypeLoader private + def import_from_modules(pattern) + modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment) + if files.empty? + raise_no_files_found(pattern) + end + + load_files(modname, files) + end + + def raise_no_files_found(pattern) + raise Puppet::ImportError, "No file(s) found for import of '#{pattern}'" + end + + def load_files(modname, files) + loaded_asts = [] + files.each do |file| + @loading_helper.do_once(file) do + loaded_asts << parse_file(file) + end + end + + loaded_asts.collect do |ast| + known_resource_types.import_ast(ast, modname) + end.flatten + end + # Return a list of all file basenames that should be tried in order # to load the object with the given fully qualified name. def name2files(fqname) diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index 570923dd7..e5cba2c41 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -28,8 +28,8 @@ class Puppet::Resource ATTRIBUTES = [:file, :line, :exported] def self.from_pson(pson) - raise ArgumentError, "No resource type provided in pson data" unless type = pson['type'] - raise ArgumentError, "No resource title provided in pson data" unless title = pson['title'] + raise ArgumentError, "No resource type provided in serialized data" unless type = pson['type'] + raise ArgumentError, "No resource title provided in serialized data" unless title = pson['title'] resource = new(type, title) @@ -47,8 +47,6 @@ class Puppet::Resource end end - resource.exported ||= false - resource end diff --git a/lib/puppet/resource/status.rb b/lib/puppet/resource/status.rb index d514a183d..4abd647c1 100644 --- a/lib/puppet/resource/status.rb +++ b/lib/puppet/resource/status.rb @@ -14,6 +14,13 @@ module Puppet YAML_ATTRIBUTES = %w{@resource @file @line @evaluation_time @change_count @out_of_sync_count @tags @time @events @out_of_sync @changed @resource_type @title @skipped @failed} + + def self.from_pson(data) + obj = self.allocate + obj.initialize_from_hash(data) + obj + end + # Provide a boolean method for each of the states. STATES.each do |attr| define_method("#{attr}?") do @@ -65,6 +72,27 @@ module Puppet @title = resource.title end + def initialize_from_hash(data) + @resource_type = data['resource_type'] + @title = data['title'] + @resource = data['resource'] + @file = data['file'] + @line = data['line'] + @evaluation_time = data['evaluation_time'] + @change_count = data['change_count'] + @out_of_sync_count = data['out_of_sync_count'] + @tags = data['tags'] + @time = data['time'] + @out_of_sync = data['out_of_sync'] + @changed = data['changed'] + @skipped = data['skipped'] + @failed = data['failed'] + + @events = data['events'].map do |event| + Puppet::Transaction::Event.from_pson(event) + end + end + def to_yaml_properties YAML_ATTRIBUTES & instance_variables end diff --git a/lib/puppet/run.rb b/lib/puppet/run.rb index 150e644a0..d378e535b 100644 --- a/lib/puppet/run.rb +++ b/lib/puppet/run.rb @@ -32,6 +32,17 @@ class Puppet::Run @options = options end + def initialize_from_hash(hash) + @options = {} + + hash['options'].each do |key, value| + @options[key.to_sym] = value + end + + @background = hash['background'] + @status = hash['status'] + end + def log_run msg = "" msg += "triggered run" % if options[:tags] @@ -62,9 +73,20 @@ class Puppet::Run self end - def self.from_pson( pson ) + def self.from_hash(hash) + obj = allocate + obj.initialize_from_hash(hash) + obj + end + + def self.from_pson(hash) + if hash['options'] + return from_hash(hash) + end + options = {} - pson.each do |key, value| + + hash.each do |key, value| options[key.to_sym] = value end diff --git a/lib/puppet/status.rb b/lib/puppet/status.rb index ea6a601f3..55bcc3d41 100644 --- a/lib/puppet/status.rb +++ b/lib/puppet/status.rb @@ -14,8 +14,12 @@ class Puppet::Status @status.to_pson end - def self.from_pson( pson ) - self.new( pson ) + def self.from_pson(pson) + if pson.include?('status') + self.new(pson['status']) + else + self.new(pson) + end end def name diff --git a/lib/puppet/transaction/event.rb b/lib/puppet/transaction/event.rb index 5adcc792e..c3f310ed1 100644 --- a/lib/puppet/transaction/event.rb +++ b/lib/puppet/transaction/event.rb @@ -16,6 +16,12 @@ class Puppet::Transaction::Event EVENT_STATUSES = %w{noop success failure audit} + def self.from_pson(data) + obj = self.allocate + obj.initialize_from_hash(data) + obj + end + def initialize(options = {}) @audited = false options.each { |attr, value| send(attr.to_s + "=", value) } @@ -23,6 +29,19 @@ class Puppet::Transaction::Event @time = Time.now end + def initialize_from_hash(data) + @audited = data['audited'] + @property = data['property'] + @previous_value = data['previous_value'] + @desired_value = data['desired_value'] + @historical_value = data['historical_value'] + @message = data['message'] + @name = data['name'].intern + @status = data['status'] + @time = data['time'] + @time = Time.parse(@time) if @time.is_a? String + end + def property=(prop) @property = prop.to_s end diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb index 184aa0f1a..670631fa7 100644 --- a/lib/puppet/transaction/report.rb +++ b/lib/puppet/transaction/report.rb @@ -19,6 +19,12 @@ class Puppet::Transaction::Report :yaml end + def self.from_pson(data) + obj = self.allocate + obj.initialize_from_hash(data) + obj + end + def <<(msg) @logs << msg self @@ -83,6 +89,39 @@ class Puppet::Transaction::Report @status = 'failed' # assume failed until the report is finalized end + def initialize_from_hash(data) + @puppet_version = data['puppet_version'] + @report_format = data['report_format'] + @configuration_version = data['configuration_version'] + @environment = data['environment'] + @status = data['status'] + @host = data['host'] + @time = data['time'] + if @time.is_a? String + @time = Time.parse(@time) + end + @kind = data['kind'] + + @metrics = {} + data['metrics'].each do |name, hash| + @metrics[name] = Puppet::Util::Metric.from_pson(hash) + end + + @logs = data['logs'].map do |record| + Puppet::Util::Log.from_pson(record) + end + + @resource_statuses = {} + data['resource_statuses'].map do |record| + if record[1] == {} + status = nil + else + status = Puppet::Resource::Status.from_pson(record[1]) + end + @resource_statuses[record[0]] = status + end + end + def name host end diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb index 000e01ee6..19f724960 100644 --- a/lib/puppet/util/log.rb +++ b/lib/puppet/util/log.rb @@ -206,6 +206,12 @@ class Puppet::Util::Log @levels.include?(level) end + def self.from_pson(data) + obj = allocate + obj.initialize_from_hash(data) + obj + end + attr_accessor :time, :remote, :file, :line, :source attr_reader :level, :message @@ -228,6 +234,19 @@ class Puppet::Util::Log Log.newmessage(self) end + def initialize_from_hash(data) + @level = data['level'].intern + @message = data['message'] + @source = data['source'] + @tags = data['tags'] + @time = data['time'] + if @time.is_a? String + @time = Time.parse(@time) + end + @file = data['file'] if data['file'] + @line = data['line'] if data['line'] + end + def message=(msg) raise ArgumentError, "Puppet::Util::Log requires a message" unless msg @message = msg.to_s diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb index 835e1d610..4e7e2319a 100644 --- a/lib/puppet/util/metric.rb +++ b/lib/puppet/util/metric.rb @@ -9,6 +9,12 @@ class Puppet::Util::Metric attr_writer :basedir + def self.from_pson(data) + metric = new(data['name'], data['label']) + metric.values = data['values'] + metric + end + # Return a specific value def [](name) if value = @values.find { |v| v[0] == name } diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb index dc8cdda36..e3b6f7188 100644 --- a/lib/puppet/util/monkey_patches.rb +++ b/lib/puppet/util/monkey_patches.rb @@ -1,4 +1,3 @@ - unless defined? JRUBY_VERSION Process.maxgroups = 1024 end @@ -34,21 +33,6 @@ end end } -if defined?(YAML::ENGINE) and YAML::ENGINE.yamler == 'psych' - def Psych.safely_load(str) - result = Psych.parse(str) - if invalid_node = result.find { |node| node.tag =~ /!map:(.*)/ || node.tag =~ /!ruby\/hash:(.*)/ } - raise ArgumentError, "Illegal YAML mapping found with tag #{invalid_node.tag}; please use !ruby/object:#{$1} instead" - else - result.to_ruby - end - end -else - def YAML.safely_load(str) - self.load(str) - end -end - def YAML.dump(*args) ZAML.dump(*args) end diff --git a/lib/puppet/vendor.rb b/lib/puppet/vendor.rb new file mode 100644 index 000000000..fdaf5c053 --- /dev/null +++ b/lib/puppet/vendor.rb @@ -0,0 +1,55 @@ +module Puppet + # Simple module to manage vendored code. + # + # To vendor a library: + # + # * Download its whole git repo or untar into `lib/puppet/vendor/<libname>` + # * Create a lib/puppetload_libraryname.rb file to add its libdir into the $:. + # (Look at existing load_xxx files, they should all follow the same pattern). + # * To load the vendored lib upfront, add a `require '<vendorlib>'`line to + # `vendor/require_vendored.rb`. + # * To load the vendored lib on demand, add a comment to `vendor/require_vendored.rb` + # to make it clear it should not be loaded upfront. + # + # At runtime, the #load_vendored method should be called. It will ensure + # all vendored libraries are added to the global `$:` path, and + # will then call execute the up-front loading specified in `vendor/require_vendored.rb`. + # + # The intention is to not change vendored libraries and to eventually + # make adding them in optional so that distros can simply adjust their + # packaging to exclude this directory and the various load_xxx.rb scripts + # if they wish to install these gems as native packages. + # + class Vendor + class << self + # @api private + def vendor_dir + File.join([File.dirname(File.expand_path(__FILE__)), "vendor"]) + end + + # @api private + def load_entry(entry) + Puppet.debug("Loading vendored #{$1}") + load "#{vendor_dir}/#{entry}" + end + + # @api private + def require_libs + require 'puppet/vendor/require_vendored' + end + + # Configures the path for all vendored libraries and loads required libraries. + # (This is the entry point for loading vendored libraries). + # + def load_vendored + Dir.entries(vendor_dir).each do |entry| + if entry.match(/load_(\w+?)\.rb$/) + load_entry entry + end + end + + require_libs + end + end + end +end diff --git a/lib/puppet/vendor/load_safe_yaml.rb b/lib/puppet/vendor/load_safe_yaml.rb new file mode 100644 index 000000000..07aa0a689 --- /dev/null +++ b/lib/puppet/vendor/load_safe_yaml.rb @@ -0,0 +1 @@ +$: << File.join([File.dirname(__FILE__), "safe_yaml/lib"]) diff --git a/lib/puppet/vendor/require_vendored.rb b/lib/puppet/vendor/require_vendored.rb new file mode 100644 index 000000000..1de24586a --- /dev/null +++ b/lib/puppet/vendor/require_vendored.rb @@ -0,0 +1,4 @@ +# This adds upfront requirements on vendored code found under lib/vendor/x +# Add one requirement per vendored package (or a comment if it is loaded on demand). + +require 'safe_yaml' diff --git a/lib/puppet/vendor/safe_yaml/CHANGES.md b/lib/puppet/vendor/safe_yaml/CHANGES.md new file mode 100644 index 000000000..1efd80cba --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/CHANGES.md @@ -0,0 +1,104 @@ +0.9.2 +----- + +- fixed error w/ parsing "!" when whitelisting tags +- fixed parsing of the number 0 (d'oh!) + +0.9.1 +----- + +- added Yecht support (JRuby) +- more bug fixes + +0.9.0 +----- + +- added `whitelist!` method for easily whitelisting tags +- added support for call-specific options +- removed deprecated methods + +0.8.6 +----- + +- fixed bug in float matcher + +0.8.5 +----- + +- performance improvements +- made less verbose by default +- bug fixes + +0.8.4 +----- + +- enhancements to parsing of integers, floats, and dates +- updated built-in whitelist +- more bug fixes + +0.8.3 +----- + +- fixed exception on parsing empty document +- fixed handling of octal & hexadecimal numbers + +0.8.2 +----- + +- bug fixes + +0.8.1 +----- + +- added `:raise_on_unknown_tag` option +- renamed `reset_defaults!` to `restore_defaults!` + +0.8 +--- + +- added tag whitelisting +- more API changes + +0.7 +--- + +- separated YAML engine support from Ruby version +- added support for binary scalars +- numerous bug fixes and enhancements + +0.6 +--- + +- several API changes +- added `SafeYAML::OPTIONS` for specifying default behavior + +0.5 +--- + +Added support for dates + +0.4 +--- + +- efficiency improvements +- made `YAML.load` use `YAML.safe_load` by default +- made symbol deserialization optional + +0.3 +--- + +Added Syck support + +0.2 +--- + +Added support for: + +- anchors & aliases +- booleans +- nils + +0.1 +--- + +Initial release
\ No newline at end of file diff --git a/lib/puppet/vendor/safe_yaml/Gemfile b/lib/puppet/vendor/safe_yaml/Gemfile new file mode 100644 index 000000000..24d7e3e5c --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/Gemfile @@ -0,0 +1,11 @@ +source "https://rubygems.org" + +gemspec + +group :development do + gem "hashie" + gem "heredoc_unindent" + gem "rake" + gem "rspec" + gem "travis-lint" +end diff --git a/lib/puppet/vendor/safe_yaml/LICENSE.txt b/lib/puppet/vendor/safe_yaml/LICENSE.txt new file mode 100644 index 000000000..4b276dd15 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2013 Dan Tao + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/puppet/vendor/safe_yaml/README.md b/lib/puppet/vendor/safe_yaml/README.md new file mode 100644 index 000000000..58b39c071 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/README.md @@ -0,0 +1,179 @@ +SafeYAML +======== + +[](http://travis-ci.org/dtao/safe_yaml) + +The **SafeYAML** gem provides an alternative implementation of `YAML.load` suitable for accepting user input in Ruby applications. Unlike Ruby's built-in implementation of `YAML.load`, SafeYAML's version will not expose apps to arbitrary code execution exploits (such as [the ones discovered](http://www.reddit.com/r/netsec/comments/167c11/serious_vulnerability_in_ruby_on_rails_allowing/) [in Rails in early 2013](http://www.h-online.com/open/news/item/Rails-developers-close-another-extremely-critical-flaw-1793511.html)). + +**If you encounter any issues with SafeYAML, check out the 'Common Issues' section below.** If you don't see anything that addresses the problem you're experiencing, by all means, [create an issue](https://github.com/dtao/safe_yaml/issues/new)! + +Installation +------------ + +Add this line to your application's Gemfile: + + gem "safe_yaml" + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install safe_yaml + +Configuration +------------- + +Configuring SafeYAML should be quick. In most cases, you will probably only have to think about two things: + +1. What do you want the `YAML` module's *default* behavior to be? Set the `SafeYAML::OPTIONS[:default_mode]` option to either `:safe` or `:unsafe` to control this. If you do neither, SafeYAML will default to `:safe` mode but will issue a warning the first time you call `YAML.load`. +2. Do you want to allow symbols by default? Set the `SafeYAML::OPTIONS[:deserialize_symbols]` option to `true` or `false` to control this. The default is `false`, which means that SafeYAML will deserialize symbols in YAML documents as strings. + +For more information on these and other options, see the "Usage" section down below. + +Explanation +----------- + +Suppose your application were to use a popular open source library which contained code like this: + +```ruby +class ClassBuilder + def []=(key, value) + @class ||= Class.new + + @class.class_eval <<-EOS + def #{key} + #{value} + end + EOS + end + + def create + @class.new + end +end +``` + +Now, if you were to use `YAML.load` on user input anywhere in your application without the SafeYAML gem installed, an attacker who suspected you were using this library could send a request with a carefully-crafted YAML string to execute arbitrary code (yes, including `system("unix command")`) on your servers. + +This simple example demonstrates the vulnerability: + +```ruby +yaml = <<-EOYAML +--- !ruby/hash:ClassBuilder +"foo; end; puts %(I'm in yr system!); def bar": "baz" +EOYAML +``` + + > YAML.load(yaml) + I'm in yr system! + => #<ClassBuilder:0x007fdbbe2e25d8 @class=#<Class:0x007fdbbe2e2510>> + +With SafeYAML, the same attacker would be thwarted: + + > require "safe_yaml" + => true + > YAML.load(yaml, :safe => true) + => {"foo; end; puts %(I'm in yr system!); def bar"=>"baz"} + +Usage +----- + +When you require the safe_yaml gem in your project, `YAML.load` is patched to accept one additional (optional) `options` parameter. This changes the method signature as follows: + +- for Syck and Psych prior to Ruby 1.9.3: `YAML.load(yaml, options={})` +- for Psych in 1.9.3 and later: `YAML.load(yaml, filename=nil, options={})` + +The most important option is the `:safe` option (default: `true`), which controls whether or not to deserialize arbitrary objects when parsing a YAML document. The other options, along with explanations, are as follows. + +- `:deserialize_symbols` (default: `false`): Controls whether or not YAML will deserialize symbols. It is probably best to only enable this option where necessary, e.g. to make trusted libraries work. Symbols receive special treatment in Ruby and are not garbage collected, which means deserializing them indiscriminately may render your site vulnerable to a DOS attack (hence `false` as a default value). + +- `:whitelisted_tags`: Accepts an array of YAML tags that designate trusted types, e.g., ones that can be deserialized without worrying about any resulting security vulnerabilities. When any of the given tags are encountered in a YAML document, the associated data will be parsed by the underlying YAML engine (Syck or Psych) for the version of Ruby you are using. See the "Whitelisting Trusted Types" section below for more information. + +- `:custom_initializers`: Similar to the `:whitelisted_tags` option, but allows you to provide your own initializers for specified tags rather than using Syck or Psyck. Accepts a hash with string tags for keys and lambdas for values. + +- `:raise_on_unknown_tag` (default: `false`): Represents the highest possible level of paranoia (not necessarily a bad thing); if the YAML engine encounters any tag other than ones that are automatically trusted by SafeYAML or that you've explicitly whitelisted, it will raise an exception. This may be a good choice if you expect to always be dealing with perfectly safe YAML and want your application to fail loudly upon encountering questionable data. + +All of the above options can be set at the global level via `SafeYAML::OPTIONS`. You can also set each one individually per call to `YAML.load`; an option explicitly passed to `load` will take precedence over an option specified globally. + +Supported Types +--------------- + +The way that SafeYAML works is by restricting the kinds of objects that can be deserialized via `YAML.load`. More specifically, only the following types of objects can be deserialized by default: + +- Hashes +- Arrays +- Strings +- Numbers +- Dates +- Times +- Booleans +- Nils + +Again, deserialization of symbols can be enabled globally by setting `SafeYAML::OPTIONS[:deserialize_symbols] = true`, or in a specific call to `YAML.load([some yaml], :deserialize_symbols => true)`. + +Whitelisting Trusted Types +-------------------------- + +SafeYAML supports whitelisting certain YAML tags for trusted types. This is handy when your application uses YAML to serialize and deserialize certain types not listed above, which you know to be free of any deserialization-related vulnerabilities. + +The easiest way to whitelist types is by calling `SafeYAML.whitelist!`, which can accept a variable number of safe types, e.g.: + +```ruby +SafeYAML.whitelist!(FrobDispenser, GobbleFactory) +``` + +You can also whitelist YAML *tags* via the `:whitelisted_tags` option: + +```ruby +# Using Syck +SafeYAML::OPTIONS[:whitelisted_tags] = ["tag:ruby.yaml.org,2002:object:OpenStruct"] + +# Using Psych +SafeYAML::OPTIONS[:whitelisted_tags] = ["!ruby/object:OpenStruct"] +``` + +And in case you were wondering: no, this feature will *not* allow would-be attackers to embed untrusted types within trusted types: + +```ruby +yaml = <<-EOYAML +--- !ruby/object:OpenStruct +table: + :backdoor: !ruby/hash:ClassBuilder + "foo; end; puts %(I'm in yr system!); def bar": "baz" +EOYAML +``` + + > YAML.safe_load(yaml) + => #<OpenStruct :backdoor={"foo; end; puts %(I'm in yr system!); def bar"=>"baz"}> + +Known Issues +------------ + +If you add SafeYAML to your project and start seeing any errors about missing keys, or you notice mysterious strings that look like `":foo"` (i.e., start with a colon), it's likely you're seeing errors from symbols being saved in YAML format. If you are able to modify the offending code, you might want to consider changing your YAML content to use plain vanilla strings instead of symbols. If not, you may need to set the `:deserialize_symbols` option to `true`, either in calls to `YAML.load` or--as a last resort--globally, with `SafeYAML::OPTIONS[:deserialize_symbols]`. + +Also be aware that some Ruby libraries, particularly those requiring inter-process communication, leverage YAML's object deserialization functionality and therefore may break or otherwise be impacted by SafeYAML. The following list includes known instances of SafeYAML's interaction with other Ruby gems: + +- [**ActiveRecord**](https://github.com/rails/rails/tree/master/activerecord): uses YAML to control serialization of model objects using the `serialize` class method. If you find that accessing serialized properties on your ActiveRecord models is causing errors, chances are you may need to: + 1. set the `:deserialize_symbols` option to `true`, + 2. whitelist some of the types in your serialized data via `SafeYAML.whitelist!` or the `:whitelisted_tags` option, or + 3. both +- [**Guard**](https://github.com/guard/guard): Uses YAML as a serialization format for notifications. The data serialized uses symbolic keys, so setting `SafeYAML::OPTIONS[:deserialize_symbols] = true` is necessary to allow Guard to work. +- [**sidekiq**](https://github.com/mperham/sidekiq): Uses a YAML configiuration file with symbolic keys, so setting `SafeYAML::OPTIONS[:deserialize_symbols] = true` should allow it to work. + +The above list will grow over time, as more issues are discovered. + +Caveat +------ + +My intention is to eventually adopt [semantic versioning](http://semver.org/) with this gem, if it ever gets to version 1.0 (i.e., doesn't become obsolete by then). Since it isn't there yet, that means that API may well change from one version to the next. Please keep that in mind if you are using it in your application. + +To be clear: my *goal* is for SafeYAML to make it as easy as possible to protect existing applications from object deserialization exploits. Any and all feedback is more than welcome! + +Requirements +------------ + +SafeYAML requires Ruby 1.8.7 or newer and works with both [Syck](http://www.ruby-doc.org/stdlib-1.8.7/libdoc/yaml/rdoc/YAML.html) and [Psych](http://github.com/tenderlove/psych). + +If you are using a version of Ruby where Psych is the default YAML engine (e.g., 1.9.3) but you want to use Syck, be sure to set `YAML::ENGINE.yamler = "syck"` **before** requiring the safe_yaml gem. diff --git a/lib/puppet/vendor/safe_yaml/Rakefile b/lib/puppet/vendor/safe_yaml/Rakefile new file mode 100644 index 000000000..3199194bc --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/Rakefile @@ -0,0 +1,6 @@ +require "rspec/core/rake_task" + +desc "Run specs" +RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = %w(--color) +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml.rb new file mode 100644 index 000000000..8670acec2 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml.rb @@ -0,0 +1,253 @@ +require "yaml" + +# This needs to be defined up front in case any internal classes need to base +# their behavior off of this. +module SafeYAML + YAML_ENGINE = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck" +end + +require "set" +require "safe_yaml/deep" +require "safe_yaml/parse/hexadecimal" +require "safe_yaml/parse/sexagesimal" +require "safe_yaml/parse/date" +require "safe_yaml/transform/transformation_map" +require "safe_yaml/transform/to_boolean" +require "safe_yaml/transform/to_date" +require "safe_yaml/transform/to_float" +require "safe_yaml/transform/to_integer" +require "safe_yaml/transform/to_nil" +require "safe_yaml/transform/to_symbol" +require "safe_yaml/transform" +require "safe_yaml/resolver" +require "safe_yaml/syck_hack" if defined?(JRUBY_VERSION) + +module SafeYAML + MULTI_ARGUMENT_YAML_LOAD = YAML.method(:load).arity != 1 + + DEFAULT_OPTIONS = Deep.freeze({ + :default_mode => nil, + :suppress_warnings => false, + :deserialize_symbols => false, + :whitelisted_tags => [], + :custom_initializers => {}, + :raise_on_unknown_tag => false + }) + + OPTIONS = Deep.copy(DEFAULT_OPTIONS) + + module_function + def restore_defaults! + OPTIONS.clear.merge!(Deep.copy(DEFAULT_OPTIONS)) + end + + def tag_safety_check!(tag, options) + return if tag.nil? || tag == "!" + if options[:raise_on_unknown_tag] && !options[:whitelisted_tags].include?(tag) && !tag_is_explicitly_trusted?(tag) + raise "Unknown YAML tag '#{tag}'" + end + end + + def whitelist!(*classes) + classes.each do |klass| + whitelist_class!(klass) + end + end + + def whitelist_class!(klass) + raise "#{klass} not a Class" unless klass.is_a?(::Class) + + klass_name = klass.name + raise "#{klass} cannot be anonymous" if klass_name.nil? || klass_name.empty? + + # Whitelist any built-in YAML tags supplied by Syck or Psych. + predefined_tag = predefined_tags[klass] + if predefined_tag + OPTIONS[:whitelisted_tags] << predefined_tag + return + end + + # Exception is exceptional (har har). + tag_class = klass < Exception ? "exception" : "object" + + tag_prefix = case YAML_ENGINE + when "psych" then "!ruby/#{tag_class}" + when "syck" then "tag:ruby.yaml.org,2002:#{tag_class}" + else raise "unknown YAML_ENGINE #{YAML_ENGINE}" + end + OPTIONS[:whitelisted_tags] << "#{tag_prefix}:#{klass_name}" + end + + def predefined_tags + if @predefined_tags.nil? + @predefined_tags = {} + + if YAML_ENGINE == "syck" + YAML.tagged_classes.each do |tag, klass| + @predefined_tags[klass] = tag + end + + else + # Special tags appear to be hard-coded in Psych: + # https://github.com/tenderlove/psych/blob/v1.3.4/lib/psych/visitors/to_ruby.rb + # Fortunately, there aren't many that SafeYAML doesn't already support. + @predefined_tags.merge!({ + Exception => "!ruby/exception", + Range => "!ruby/range", + Regexp => "!ruby/regexp", + }) + end + end + + @predefined_tags + end + + if YAML_ENGINE == "psych" + def tag_is_explicitly_trusted?(tag) + false + end + + else + TRUSTED_TAGS = Set.new([ + "tag:yaml.org,2002:binary", + "tag:yaml.org,2002:bool#no", + "tag:yaml.org,2002:bool#yes", + "tag:yaml.org,2002:float", + "tag:yaml.org,2002:float#fix", + "tag:yaml.org,2002:int", + "tag:yaml.org,2002:map", + "tag:yaml.org,2002:null", + "tag:yaml.org,2002:seq", + "tag:yaml.org,2002:str", + "tag:yaml.org,2002:timestamp", + "tag:yaml.org,2002:timestamp#ymd" + ]).freeze + + def tag_is_explicitly_trusted?(tag) + TRUSTED_TAGS.include?(tag) + end + end +end + +module YAML + def self.load_with_options(yaml, *original_arguments) + filename, options = filename_and_options_from_arguments(original_arguments) + safe_mode = safe_mode_from_options("load", options) + arguments = [yaml] + + if safe_mode == :safe + arguments << filename if SafeYAML::YAML_ENGINE == "psych" + arguments << options_for_safe_load(options) + safe_load(*arguments) + else + arguments << filename if SafeYAML::MULTI_ARGUMENT_YAML_LOAD + unsafe_load(*arguments) + end + end + + def self.load_file_with_options(file, options={}) + safe_mode = safe_mode_from_options("load_file", options) + if safe_mode == :safe + safe_load_file(file, options_for_safe_load(options)) + else + unsafe_load_file(file) + end + end + + if SafeYAML::YAML_ENGINE == "psych" + require "safe_yaml/psych_handler" + require "safe_yaml/psych_resolver" + require "safe_yaml/safe_to_ruby_visitor" + + def self.safe_load(yaml, filename=nil, options={}) + # If the user hasn't whitelisted any tags, we can go with this implementation which is + # significantly faster. + if (options && options[:whitelisted_tags] || SafeYAML::OPTIONS[:whitelisted_tags]).empty? + safe_handler = SafeYAML::PsychHandler.new(options) + arguments_for_parse = [yaml] + arguments_for_parse << filename if SafeYAML::MULTI_ARGUMENT_YAML_LOAD + Psych::Parser.new(safe_handler).parse(*arguments_for_parse) + return safe_handler.result || false + + else + safe_resolver = SafeYAML::PsychResolver.new(options) + tree = SafeYAML::MULTI_ARGUMENT_YAML_LOAD ? + Psych.parse(yaml, filename) : + Psych.parse(yaml) + return safe_resolver.resolve_node(tree) + end + end + + def self.safe_load_file(filename, options={}) + File.open(filename, 'r:bom|utf-8') { |f| self.safe_load(f, filename, options) } + end + + def self.unsafe_load_file(filename) + if SafeYAML::MULTI_ARGUMENT_YAML_LOAD + # https://github.com/tenderlove/psych/blob/v1.3.2/lib/psych.rb#L296-298 + File.open(filename, 'r:bom|utf-8') { |f| self.unsafe_load(f, filename) } + else + # https://github.com/tenderlove/psych/blob/v1.2.2/lib/psych.rb#L231-233 + self.unsafe_load File.open(filename) + end + end + + else + require "safe_yaml/syck_resolver" + require "safe_yaml/syck_node_monkeypatch" + + def self.safe_load(yaml, options={}) + resolver = SafeYAML::SyckResolver.new(SafeYAML::OPTIONS.merge(options || {})) + tree = YAML.parse(yaml) + return resolver.resolve_node(tree) + end + + def self.safe_load_file(filename, options={}) + File.open(filename) { |f| self.safe_load(f, options) } + end + + def self.unsafe_load_file(filename) + # https://github.com/indeyets/syck/blob/master/ext/ruby/lib/yaml.rb#L133-135 + File.open(filename) { |f| self.unsafe_load(f) } + end + end + + class << self + alias_method :unsafe_load, :load + alias_method :load, :load_with_options + alias_method :load_file, :load_file_with_options + + private + def filename_and_options_from_arguments(arguments) + if arguments.count == 1 + if arguments.first.is_a?(String) + return arguments.first, {} + else + return nil, arguments.first || {} + end + + else + return arguments.first, arguments.last || {} + end + end + + def safe_mode_from_options(method, options={}) + if options[:safe].nil? + safe_mode = SafeYAML::OPTIONS[:default_mode] || :safe + if SafeYAML::OPTIONS[:default_mode].nil? && !SafeYAML::OPTIONS[:suppress_warnings] + Kernel.warn "Called '#{method}' without the :safe option -- defaulting to #{safe_mode} mode." + SafeYAML::OPTIONS[:suppress_warnings] = true + end + return safe_mode + end + + options[:safe] ? :safe : :unsafe + end + + def options_for_safe_load(base_options) + options = base_options.dup + options.delete(:safe) + options + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/deep.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/deep.rb new file mode 100644 index 000000000..6a5e037fb --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/deep.rb @@ -0,0 +1,34 @@ +module SafeYAML + class Deep + def self.freeze(object) + object.each do |*entry| + value = entry.last + case value + when String, Regexp + value.freeze + when Enumerable + Deep.freeze(value) + end + end + + return object.freeze + end + + def self.copy(object) + duplicate = object.dup rescue object + + case object + when Array + (0...duplicate.count).each do |i| + duplicate[i] = Deep.copy(duplicate[i]) + end + when Hash + duplicate.keys.each do |key| + duplicate[key] = Deep.copy(duplicate[key]) + end + end + + duplicate + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/date.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/date.rb new file mode 100644 index 000000000..077294145 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/date.rb @@ -0,0 +1,27 @@ +module SafeYAML + class Parse + class Date + # This one's easy enough :) + DATE_MATCHER = /\A(\d{4})-(\d{2})-(\d{2})\Z/.freeze + + # This unbelievable little gem is taken basically straight from the YAML spec, but made + # slightly more readable (to my poor eyes at least) to me: + # http://yaml.org/type/timestamp.html + TIME_MATCHER = /\A\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d{2}:\d{2}(?:\.\d*)?\s*(?:Z|[-+]\d{1,2}(?::?\d{2})?)?\Z/.freeze + + SECONDS_PER_DAY = 60 * 60 * 24 + MICROSECONDS_PER_SECOND = 1000000 + + # So this is weird. In Ruby 1.8.7, the DateTime#sec_fraction method returned fractional + # seconds in units of DAYS for some reason. In 1.9.2, they changed the units -- much more + # reasonably -- to seconds. + SEC_FRACTION_MULTIPLIER = RUBY_VERSION == "1.8.7" ? (SECONDS_PER_DAY * MICROSECONDS_PER_SECOND) : MICROSECONDS_PER_SECOND + + def self.value(value) + d = DateTime.parse(value) + usec = d.sec_fraction * SEC_FRACTION_MULTIPLIER + Time.utc(d.year, d.month, d.day, d.hour, d.min, d.sec, usec) - (d.offset * SECONDS_PER_DAY) + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/hexadecimal.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/hexadecimal.rb new file mode 100644 index 000000000..8da362495 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/hexadecimal.rb @@ -0,0 +1,12 @@ +module SafeYAML + class Parse + class Hexadecimal + MATCHER = /\A[-+]?0x[0-9a-fA-F_]+\Z/.freeze + + def self.value(value) + # This is safe to do since we already validated the value. + return Integer(value.gsub(/_/, "")) + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/sexagesimal.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/sexagesimal.rb new file mode 100644 index 000000000..3fff5bb16 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/sexagesimal.rb @@ -0,0 +1,26 @@ +module SafeYAML + class Parse + class Sexagesimal + INTEGER_MATCHER = /\A[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\Z/.freeze + FLOAT_MATCHER = /\A[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*\Z/.freeze + + def self.value(value) + before_decimal, after_decimal = value.split(".") + + whole_part = 0 + multiplier = 1 + + before_decimal = before_decimal.split(":") + until before_decimal.empty? + whole_part += (Float(before_decimal.pop) * multiplier) + multiplier *= 60 + end + + result = whole_part + result += Float("." + after_decimal) unless after_decimal.nil? + result *= -1 if value[0] == "-" + result + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_handler.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_handler.rb new file mode 100644 index 000000000..327fbc193 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_handler.rb @@ -0,0 +1,92 @@ +require "psych" +require "base64" + +module SafeYAML + class PsychHandler < Psych::Handler + def initialize(options) + @options = SafeYAML::OPTIONS.merge(options || {}) + @initializers = @options[:custom_initializers] || {} + @anchors = {} + @stack = [] + @current_key = nil + @result = nil + end + + def result + @result + end + + def add_to_current_structure(value, anchor=nil, quoted=nil, tag=nil) + value = Transform.to_proper_type(value, quoted, tag, @options) + + @anchors[anchor] = value if anchor + + if @result.nil? + @result = value + @current_structure = @result + return + end + + if @current_structure.respond_to?(:<<) + @current_structure << value + + elsif @current_structure.respond_to?(:[]=) + if @current_key.nil? + @current_key = value + + else + if @current_key == "<<" + @current_structure.merge!(value) + else + @current_structure[@current_key] = value + end + + @current_key = nil + end + + else + raise "Don't know how to add to a #{@current_structure.class}!" + end + end + + def end_current_structure + @stack.pop + @current_structure = @stack.last + end + + def streaming? + false + end + + # event handlers + def alias(anchor) + add_to_current_structure(@anchors[anchor]) + end + + def scalar(value, anchor, tag, plain, quoted, style) + add_to_current_structure(value, anchor, quoted, tag) + end + + def start_mapping(anchor, tag, implicit, style) + map = @initializers.include?(tag) ? @initializers[tag].call : {} + self.add_to_current_structure(map, anchor) + @current_structure = map + @stack.push(map) + end + + def end_mapping + self.end_current_structure() + end + + def start_sequence(anchor, tag, implicit, style) + seq = @initializers.include?(tag) ? @initializers[tag].call : [] + self.add_to_current_structure(seq, anchor) + @current_structure = seq + @stack.push(seq) + end + + def end_sequence + self.end_current_structure() + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_resolver.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_resolver.rb new file mode 100644 index 000000000..851989bef --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_resolver.rb @@ -0,0 +1,52 @@ +module SafeYAML + class PsychResolver < Resolver + NODE_TYPES = { + Psych::Nodes::Document => :root, + Psych::Nodes::Mapping => :map, + Psych::Nodes::Sequence => :seq, + Psych::Nodes::Scalar => :scalar, + Psych::Nodes::Alias => :alias + }.freeze + + def initialize(options={}) + super + @aliased_nodes = {} + end + + def resolve_root(root) + resolve_seq(root).first + end + + def resolve_alias(node) + resolve_node(@aliased_nodes[node.anchor]) + end + + def native_resolve(node) + @visitor ||= SafeYAML::SafeToRubyVisitor.new(self) + @visitor.accept(node) + end + + def get_node_type(node) + NODE_TYPES[node.class] + end + + def get_node_tag(node) + node.tag + end + + def get_node_value(node) + @aliased_nodes[node.anchor] = node if node.respond_to?(:anchor) && node.anchor + + case get_node_type(node) + when :root, :map, :seq + node.children + when :scalar + node.value + end + end + + def value_is_quoted?(node) + node.quoted + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/resolver.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/resolver.rb new file mode 100644 index 000000000..d15343f6f --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/resolver.rb @@ -0,0 +1,94 @@ +module SafeYAML + class Resolver + def initialize(options) + @options = SafeYAML::OPTIONS.merge(options || {}) + @whitelist = @options[:whitelisted_tags] || [] + @initializers = @options[:custom_initializers] || {} + @raise_on_unknown_tag = @options[:raise_on_unknown_tag] + end + + def resolve_node(node) + return node if !node + return self.native_resolve(node) if tag_is_whitelisted?(self.get_node_tag(node)) + + case self.get_node_type(node) + when :root + resolve_root(node) + when :map + resolve_map(node) + when :seq + resolve_seq(node) + when :scalar + resolve_scalar(node) + when :alias + resolve_alias(node) + else + raise "Don't know how to resolve this node: #{node.inspect}" + end + end + + def resolve_map(node) + tag = get_and_check_node_tag(node) + hash = @initializers.include?(tag) ? @initializers[tag].call : {} + map = normalize_map(self.get_node_value(node)) + + # Take the "<<" key nodes first, as these are meant to approximate a form of inheritance. + inheritors = map.select { |key_node, value_node| resolve_node(key_node) == "<<" } + inheritors.each do |key_node, value_node| + merge_into_hash(hash, resolve_node(value_node)) + end + + # All that's left should be normal (non-"<<") nodes. + (map - inheritors).each do |key_node, value_node| + hash[resolve_node(key_node)] = resolve_node(value_node) + end + + return hash + end + + def resolve_seq(node) + seq = self.get_node_value(node) + + tag = get_and_check_node_tag(node) + arr = @initializers.include?(tag) ? @initializers[tag].call : [] + + seq.inject(arr) { |array, node| array << resolve_node(node) } + end + + def resolve_scalar(node) + Transform.to_proper_type(self.get_node_value(node), self.value_is_quoted?(node), get_and_check_node_tag(node), @options) + end + + def get_and_check_node_tag(node) + tag = self.get_node_tag(node) + SafeYAML.tag_safety_check!(tag, @options) + tag + end + + def tag_is_whitelisted?(tag) + @whitelist.include?(tag) + end + + def options + @options + end + + private + def normalize_map(map) + # Syck creates Hashes from maps. + if map.is_a?(Hash) + map.inject([]) { |arr, key_and_value| arr << key_and_value } + + # Psych is really weird; it flattens out a Hash completely into: [key, value, key, value, ...] + else + map.each_slice(2).to_a + end + end + + def merge_into_hash(hash, array) + array.each do |key, value| + hash[key] = value + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/safe_to_ruby_visitor.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/safe_to_ruby_visitor.rb new file mode 100644 index 000000000..0a8c4228d --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/safe_to_ruby_visitor.rb @@ -0,0 +1,17 @@ +module SafeYAML + class SafeToRubyVisitor < Psych::Visitors::ToRuby + def initialize(resolver) + super() + @resolver = resolver + end + + def accept(node) + if node.tag + SafeYAML.tag_safety_check!(node.tag, @resolver.options) + return super + end + + @resolver.resolve_node(node) + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_hack.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_hack.rb new file mode 100644 index 000000000..08a5e478e --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_hack.rb @@ -0,0 +1,36 @@ +# Hack to JRuby 1.8's YAML Parser Yecht +# +# This file is always loaded AFTER either syck or psych are already +# loaded. It then looks at what constants are available and creates +# a consistent view on all rubys. +# +# Taken from rubygems and modified. +# See https://github.com/rubygems/rubygems/blob/master/lib/rubygems/syck_hack.rb + +module YAML + # In newer 1.9.2, there is a Syck toplevel constant instead of it + # being underneith YAML. If so, reference it back under YAML as + # well. + if defined? ::Syck + # for tests that change YAML::ENGINE + # 1.8 does not support the second argument to const_defined? + remove_const :Syck rescue nil + + Syck = ::Syck + + # JRuby's "Syck" is called "Yecht" + elsif defined? YAML::Yecht + Syck = YAML::Yecht + end +end + +# Sometime in the 1.9 dev cycle, the Syck constant was moved from under YAML +# to be a toplevel constant. So gemspecs created under these versions of Syck +# will have references to Syck::DefaultKey. +# +# So we need to be sure that we reference Syck at the toplevel too so that +# we can always load these kind of gemspecs. +# +if !defined?(Syck) + Syck = YAML::Syck +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_node_monkeypatch.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_node_monkeypatch.rb new file mode 100644 index 000000000..c026376cd --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_node_monkeypatch.rb @@ -0,0 +1,43 @@ +# This is, admittedly, pretty insane. Fundamentally the challenge here is this: if we want to allow +# whitelisting of tags (while still leveraging Syck's internal functionality), then we have to +# change how Syck::Node#transform works. But since we (SafeYAML) do not control instantiation of +# Syck::Node objects, we cannot, for example, subclass Syck::Node and override #tranform the "easy" +# way. So the only choice is to monkeypatch, like this. And the only way to make this work +# recursively with potentially call-specific options (that my feeble brain can think of) is to set +# pseudo-global options on the first call and unset them once the recursive stack has fully unwound. + +monkeypatch = <<-EORUBY + class Node + @@safe_transform_depth = 0 + @@safe_transform_whitelist = nil + + def safe_transform(options={}) + begin + @@safe_transform_depth += 1 + @@safe_transform_whitelist ||= options[:whitelisted_tags] + + if self.type_id + SafeYAML.tag_safety_check!(self.type_id, options) + return unsafe_transform if @@safe_transform_whitelist.include?(self.type_id) + end + + SafeYAML::SyckResolver.new.resolve_node(self) + + ensure + @@safe_transform_depth -= 1 + if @@safe_transform_depth == 0 + @@safe_transform_whitelist = nil + end + end + end + + alias_method :unsafe_transform, :transform + alias_method :transform, :safe_transform + end +EORUBY + +if defined?(YAML::Syck::Node) + YAML::Syck.module_eval monkeypatch +else + Syck.module_eval monkeypatch +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_resolver.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_resolver.rb new file mode 100644 index 000000000..10d55ab37 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_resolver.rb @@ -0,0 +1,38 @@ +module SafeYAML + class SyckResolver < Resolver + QUOTE_STYLES = [ + :quote1, + :quote2 + ].freeze + + NODE_TYPES = { + Hash => :map, + Array => :seq, + String => :scalar + }.freeze + + def initialize(options={}) + super + end + + def native_resolve(node) + node.transform(self.options) + end + + def get_node_type(node) + NODE_TYPES[node.value.class] + end + + def get_node_tag(node) + node.type_id + end + + def get_node_value(node) + node.value + end + + def value_is_quoted?(node) + QUOTE_STYLES.include?(node.instance_variable_get(:@style)) + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform.rb new file mode 100644 index 000000000..d61d1a995 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform.rb @@ -0,0 +1,41 @@ +require 'base64' + +module SafeYAML + class Transform + TRANSFORMERS = [ + Transform::ToSymbol.new, + Transform::ToInteger.new, + Transform::ToFloat.new, + Transform::ToNil.new, + Transform::ToBoolean.new, + Transform::ToDate.new + ] + + def self.to_guessed_type(value, quoted=false, options=nil) + return value if quoted + + if value.is_a?(String) + TRANSFORMERS.each do |transformer| + success, transformed_value = transformer.method(:transform?).arity == 1 ? + transformer.transform?(value) : + transformer.transform?(value, options) + + return transformed_value if success + end + end + + value + end + + def self.to_proper_type(value, quoted=false, tag=nil, options=nil) + case tag + when "tag:yaml.org,2002:binary", "x-private:binary", "!binary" + decoded = Base64.decode64(value) + decoded = decoded.force_encoding(value.encoding) if decoded.respond_to?(:force_encoding) + decoded + else + self.to_guessed_type(value, quoted, options) + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_boolean.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_boolean.rb new file mode 100644 index 000000000..99dc85efe --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_boolean.rb @@ -0,0 +1,21 @@ +module SafeYAML + class Transform + class ToBoolean + include TransformationMap + + set_predefined_values({ + "yes" => true, + "on" => true, + "true" => true, + "no" => false, + "off" => false, + "false" => false + }) + + def transform?(value) + return false if value.length > 5 + return PREDEFINED_VALUES.include?(value), PREDEFINED_VALUES[value] + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_date.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_date.rb new file mode 100644 index 000000000..f8f12654b --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_date.rb @@ -0,0 +1,11 @@ +module SafeYAML + class Transform + class ToDate + def transform?(value) + return true, Date.parse(value) if Parse::Date::DATE_MATCHER.match(value) + return true, Parse::Date.value(value) if Parse::Date::TIME_MATCHER.match(value) + false + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_float.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_float.rb new file mode 100644 index 000000000..4ee3f5fbf --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_float.rb @@ -0,0 +1,33 @@ +module SafeYAML + class Transform + class ToFloat + Infinity = 1.0 / 0.0 + NaN = 0.0 / 0.0 + + PREDEFINED_VALUES = { + ".inf" => Infinity, + ".Inf" => Infinity, + ".INF" => Infinity, + "-.inf" => -Infinity, + "-.Inf" => -Infinity, + "-.INF" => -Infinity, + ".nan" => NaN, + ".NaN" => NaN, + ".NAN" => NaN, + }.freeze + + MATCHER = /\A[-+]?(?:\d[\d_]*)?\.[\d_]+(?:[eE][-+][\d]+)?\Z/.freeze + + def transform?(value) + return true, Float(value) if MATCHER.match(value) + try_edge_cases?(value) + end + + def try_edge_cases?(value) + return true, PREDEFINED_VALUES[value] if PREDEFINED_VALUES.include?(value) + return true, Parse::Sexagesimal.value(value) if Parse::Sexagesimal::FLOAT_MATCHER.match(value) + return false + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_integer.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_integer.rb new file mode 100644 index 000000000..25222d2a8 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_integer.rb @@ -0,0 +1,25 @@ +module SafeYAML + class Transform + class ToInteger + MATCHERS = Deep.freeze([ + /\A[-+]?(0|([1-9][0-9_,]*))\Z/, # decimal + /\A0[0-7]+\Z/, # octal + /\A0x[0-9a-f]+\Z/i, # hexadecimal + /\A0b[01_]+\Z/ # binary + ]) + + def transform?(value) + MATCHERS.each do |matcher| + return true, Integer(value.gsub(",", "")) if matcher.match(value) + end + try_edge_cases?(value) + end + + def try_edge_cases?(value) + return true, Parse::Hexadecimal.value(value) if Parse::Hexadecimal::MATCHER.match(value) + return true, Parse::Sexagesimal.value(value) if Parse::Sexagesimal::INTEGER_MATCHER.match(value) + return false + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_nil.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_nil.rb new file mode 100644 index 000000000..258ad462f --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_nil.rb @@ -0,0 +1,18 @@ +module SafeYAML + class Transform + class ToNil + include TransformationMap + + set_predefined_values({ + "" => nil, + "~" => nil, + "null" => nil, + }) + + def transform?(value) + return false if value.length > 4 + return PREDEFINED_VALUES.include?(value), PREDEFINED_VALUES[value] + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_symbol.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_symbol.rb new file mode 100644 index 000000000..d7eb49422 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_symbol.rb @@ -0,0 +1,13 @@ +module SafeYAML + class Transform + class ToSymbol + MATCHER = /\A:"?(\w+)"?\Z/.freeze + + def transform?(value, options=nil) + options ||= SafeYAML::OPTIONS + return false unless options[:deserialize_symbols] && MATCHER.match(value) + return true, $1.to_sym + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/transformation_map.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/transformation_map.rb new file mode 100644 index 000000000..d4e45ec52 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/transformation_map.rb @@ -0,0 +1,47 @@ +module SafeYAML + class Transform + module TransformationMap + def self.included(base) + base.extend(ClassMethods) + end + + class CaseAgnosticMap < Hash + def initialize(*args) + super + end + + def include?(key) + super(key.downcase) + end + + def [](key) + super(key.downcase) + end + + # OK, I actually don't think it's all that important that this map be + # frozen. + def freeze + self + end + end + + module ClassMethods + def set_predefined_values(predefined_values) + if SafeYAML::YAML_ENGINE == "syck" + expanded_map = predefined_values.inject({}) do |hash, (key, value)| + hash[key] = value + hash[key.capitalize] = value + hash[key.upcase] = value + hash + end + else + expanded_map = CaseAgnosticMap.new + expanded_map.merge!(predefined_values) + end + + self.const_set(:PREDEFINED_VALUES, expanded_map.freeze) + end + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/lib/safe_yaml/version.rb b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/version.rb new file mode 100644 index 000000000..056d2b0ba --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/lib/safe_yaml/version.rb @@ -0,0 +1,3 @@ +module SafeYAML + VERSION = "0.9.2" +end diff --git a/lib/puppet/vendor/safe_yaml/run_specs_all_ruby_versions.sh b/lib/puppet/vendor/safe_yaml/run_specs_all_ruby_versions.sh new file mode 100755 index 000000000..4c1778719 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/run_specs_all_ruby_versions.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" + +rvm use 1.8.7@safe_yaml +rake spec + +rvm use 1.9.2@safe_yaml +YAMLER=syck rake spec + +rvm use 1.9.3@safe_yaml +YAMLER=syck rake spec + +rvm use 1.9.2@safe_yaml +YAMLER=psych rake spec + +rvm use 1.9.3@safe_yaml +YAMLER=psych rake spec + +rvm use 2.0.0@safe_yaml +YAMLER=psych rake spec diff --git a/lib/puppet/vendor/safe_yaml/safe_yaml.gemspec b/lib/puppet/vendor/safe_yaml/safe_yaml.gemspec new file mode 100644 index 000000000..dbcd92691 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/safe_yaml.gemspec @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +require File.join(File.dirname(__FILE__), "lib", "safe_yaml", "version") + +Gem::Specification.new do |gem| + gem.name = "safe_yaml" + gem.version = SafeYAML::VERSION + gem.authors = "Dan Tao" + gem.email = "daniel.tao@gmail.com" + gem.description = %q{Parse YAML safely, without that pesky arbitrary object deserialization vulnerability} + gem.summary = %q{SameYAML provides an alternative implementation of YAML.load suitable for accepting user input in Ruby applications.} + gem.homepage = "http://dtao.github.com/safe_yaml/" + gem.license = "MIT" + gem.files = `git ls-files`.split($\) + gem.test_files = gem.files.grep(%r{^spec/}) + gem.require_paths = ["lib"] + + gem.required_ruby_version = ">= 1.8.7" +end diff --git a/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.2.yaml b/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.2.yaml new file mode 100644 index 000000000..bdd70cc67 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.2.yaml @@ -0,0 +1,2 @@ +--- !ruby/object:ExploitableBackDoor +foo: bar diff --git a/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.3.yaml b/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.3.yaml new file mode 100644 index 000000000..c24e04b8d --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.3.yaml @@ -0,0 +1,2 @@ +--- !ruby/hash:ExploitableBackDoor +foo: bar diff --git a/lib/puppet/vendor/safe_yaml/spec/psych_resolver_spec.rb b/lib/puppet/vendor/safe_yaml/spec/psych_resolver_spec.rb new file mode 100644 index 000000000..269be5d28 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/psych_resolver_spec.rb @@ -0,0 +1,10 @@ +require File.join(File.dirname(__FILE__), "spec_helper") + +if SafeYAML::YAML_ENGINE == "psych" + require "safe_yaml/psych_resolver" + + describe SafeYAML::PsychResolver do + include ResolverSpecs + let(:resolver) { SafeYAML::PsychResolver.new } + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/resolver_specs.rb b/lib/puppet/vendor/safe_yaml/spec/resolver_specs.rb new file mode 100644 index 000000000..5e070b07f --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/resolver_specs.rb @@ -0,0 +1,250 @@ +module ResolverSpecs + def self.included(base) + base.module_eval do + let(:resolver) { nil } + let(:result) { @result } + + def parse(yaml) + tree = YAML.parse(yaml.unindent) + @result = resolver.resolve_node(tree) + end + + # Isn't this how I should've been doing it all along? + def parse_and_test(yaml) + parse(yaml) + @result.should == YAML.unsafe_load(yaml) + end + + context "by default" do + it "translates maps to hashes" do + parse <<-YAML + potayto: potahto + tomayto: tomahto + YAML + + result.should == { + "potayto" => "potahto", + "tomayto" => "tomahto" + } + end + + it "translates sequences to arrays" do + parse <<-YAML + - foo + - bar + - baz + YAML + + result.should == ["foo", "bar", "baz"] + end + + it "translates most values to strings" do + parse "string: value" + result.should == { "string" => "value" } + end + + it "does not deserialize symbols" do + parse ":symbol: value" + result.should == { ":symbol" => "value" } + end + + it "translates valid integral numbers to integers" do + parse "integer: 1" + result.should == { "integer" => 1 } + end + + it "translates valid decimal numbers to floats" do + parse "float: 3.14" + result.should == { "float" => 3.14 } + end + + it "translates valid dates" do + parse "date: 2013-01-24" + result.should == { "date" => Date.parse("2013-01-24") } + end + + it "translates valid true/false values to booleans" do + parse <<-YAML + - yes + - true + - no + - false + YAML + + result.should == [true, true, false, false] + end + + it "translates valid nulls to nil" do + parse <<-YAML + - + - ~ + - null + YAML + + result.should == [nil] * 3 + end + + it "matches the behavior of the underlying YAML engine w/ respect to capitalization of boolean values" do + parse_and_test <<-YAML + - true + - True + - TRUE + - tRue + - TRue + - False + - FALSE + - fAlse + - FALse + YAML + + # using Syck: [true, true, true, "tRue", "TRue", false, false, "fAlse", "FALse"] + # using Psych: all booleans + end + + it "matches the behavior of the underlying YAML engine w/ respect to capitalization of nil values" do + parse_and_test <<-YAML + - Null + - NULL + - nUll + - NUll + YAML + + # using Syck: [nil, nil, "nUll", "NUll"] + # using Psych: all nils + end + + it "translates quoted empty strings to strings (not nil)" do + parse "foo: ''" + result.should == { "foo" => "" } + end + + it "correctly reverse-translates strings encoded via #to_yaml" do + parse "5.10".to_yaml + result.should == "5.10" + end + + it "does not specially parse any double-quoted strings" do + parse <<-YAML + - "1" + - "3.14" + - "true" + - "false" + - "2013-02-03" + - "2013-02-03 16:27:00 -0600" + YAML + + result.should == ["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"] + end + + it "does not specially parse any single-quoted strings" do + parse <<-YAML + - '1' + - '3.14' + - 'true' + - 'false' + - '2013-02-03' + - '2013-02-03 16:27:00 -0600' + YAML + + result.should == ["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"] + end + + it "deals just fine with nested maps" do + parse <<-YAML + foo: + bar: + marco: polo + YAML + + result.should == { "foo" => { "bar" => { "marco" => "polo" } } } + end + + it "deals just fine with nested sequences" do + parse <<-YAML + - foo + - + - bar1 + - bar2 + - + - baz1 + - baz2 + YAML + + result.should == ["foo", ["bar1", "bar2", ["baz1", "baz2"]]] + end + + it "applies the same transformations to keys as to values" do + parse <<-YAML + foo: string + :bar: symbol + 1: integer + 3.14: float + 2013-01-24: date + YAML + + result.should == { + "foo" => "string", + ":bar" => "symbol", + 1 => "integer", + 3.14 => "float", + Date.parse("2013-01-24") => "date", + } + end + + it "applies the same transformations to elements in sequences as to all values" do + parse <<-YAML + - foo + - :bar + - 1 + - 3.14 + - 2013-01-24 + YAML + + result.should == ["foo", ":bar", 1, 3.14, Date.parse("2013-01-24")] + end + end + + context "for Ruby version #{RUBY_VERSION}" do + it "translates valid time values" do + parse "time: 2013-01-29 05:58:00 -0800" + result.should == { "time" => Time.utc(2013, 1, 29, 13, 58, 0) } + end + + it "applies the same transformation to elements in sequences" do + parse "- 2013-01-29 05:58:00 -0800" + result.should == [Time.utc(2013, 1, 29, 13, 58, 0)] + end + + it "applies the same transformation to keys" do + parse "2013-01-29 05:58:00 -0800: time" + result.should == { Time.utc(2013, 1, 29, 13, 58, 0) => "time" } + end + end + + context "with symbol deserialization enabled" do + before :each do + SafeYAML::OPTIONS[:deserialize_symbols] = true + end + + after :each do + SafeYAML.restore_defaults! + end + + it "translates values starting with ':' to symbols" do + parse "symbol: :value" + result.should == { "symbol" => :value } + end + + it "applies the same transformation to keys" do + parse ":bar: symbol" + result.should == { :bar => "symbol" } + end + + it "applies the same transformation to elements in sequences" do + parse "- :bar" + result.should == [:bar] + end + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb b/lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb new file mode 100644 index 000000000..d454b162e --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb @@ -0,0 +1,702 @@ +require File.join(File.dirname(__FILE__), "spec_helper") + +require "exploitable_back_door" + +describe YAML do + # Essentially stolen from: + # https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L10-25 + def silence_warnings + $VERBOSE = nil; yield + ensure + $VERBOSE = true + end + + def safe_load_round_trip(object, options={}) + yaml = object.to_yaml + if SafeYAML::YAML_ENGINE == "psych" + YAML.safe_load(yaml, nil, options) + else + YAML.safe_load(yaml, options) + end + end + + before :each do + SafeYAML.restore_defaults! + end + + after :each do + SafeYAML.restore_defaults! + end + + describe "unsafe_load" do + if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3" + it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do + backdoor = YAML.unsafe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n") + backdoor.should be_exploited_through_setter + end + + it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do + backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n") + backdoor.should be_exploited_through_init_with + end + end + + it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do + backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n") + backdoor.should be_exploited_through_ivars + end + + context "with special whitelisted tags defined" do + before :each do + SafeYAML::whitelist!(OpenStruct) + end + + it "effectively ignores the whitelist (since everything is whitelisted)" do + result = YAML.unsafe_load <<-YAML.unindent + --- !ruby/object:OpenStruct + table: + :backdoor: !ruby/object:ExploitableBackDoor + foo: bar + YAML + + result.should be_a(OpenStruct) + result.backdoor.should be_exploited_through_ivars + end + end + end + + describe "safe_load" do + it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do + object = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n") + object.should_not be_a(ExploitableBackDoor) + end + + it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do + object = YAML.safe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n") + object.should_not be_a(ExploitableBackDoor) + end + + context "for YAML engine #{SafeYAML::YAML_ENGINE}" do + if SafeYAML::YAML_ENGINE == "psych" + let(:options) { nil } + let(:arguments) { ["foo: bar", nil, options] } + + context "when no tags are whitelisted" do + it "constructs a SafeYAML::PsychHandler to resolve nodes as they're parsed, for optimal performance" do + Psych::Parser.should_receive(:new).with an_instance_of(SafeYAML::PsychHandler) + # This won't work now; we just want to ensure Psych::Parser#parse was in fact called. + YAML.safe_load(*arguments) rescue nil + end + end + + context "when whitelisted tags are specified" do + let(:options) { + { :whitelisted_tags => ["foo"] } + } + + it "instead uses Psych to construct a full tree before examining the nodes" do + Psych.should_receive(:parse) + # This won't work now; we just want to ensure Psych::Parser#parse was in fact called. + YAML.safe_load(*arguments) rescue nil + end + end + end + + if SafeYAML::YAML_ENGINE == "syck" + it "uses Syck internally to parse YAML" do + YAML.should_receive(:parse).with("foo: bar") + # This won't work now; we just want to ensure YAML::parse was in fact called. + YAML.safe_load("foo: bar") rescue nil + end + end + end + + it "loads a plain ol' YAML document just fine" do + result = YAML.safe_load <<-YAML.unindent + foo: + number: 1 + string: Hello, there! + symbol: :blah + sequence: + - hi + - bye + YAML + + result.should == { + "foo" => { + "number" => 1, + "string" => "Hello, there!", + "symbol" => ":blah", + "sequence" => ["hi", "bye"] + } + } + end + + it "works for YAML documents with anchors and aliases" do + result = YAML.safe_load <<-YAML + - &id001 {} + - *id001 + - *id001 + YAML + + result.should == [{}, {}, {}] + end + + it "works for YAML documents with binary tagged keys" do + result = YAML.safe_load <<-YAML + ? !!binary > + Zm9v + : "bar" + ? !!binary > + YmFy + : "baz" + YAML + + result.should == {"foo" => "bar", "bar" => "baz"} + end + + it "works for YAML documents with binary tagged values" do + result = YAML.safe_load <<-YAML + "foo": !!binary > + YmFy + "bar": !!binary > + YmF6 + YAML + + result.should == {"foo" => "bar", "bar" => "baz"} + end + + it "works for YAML documents with binary tagged array values" do + result = YAML.safe_load <<-YAML + - !binary |- + Zm9v + - !binary |- + YmFy + YAML + + result.should == ["foo", "bar"] + end + + it "works for YAML documents with sections" do + result = YAML.safe_load <<-YAML + mysql: &mysql + adapter: mysql + pool: 30 + login: &login + username: user + password: password123 + development: &development + <<: *mysql + <<: *login + host: localhost + YAML + + result.should == { + "mysql" => { + "adapter" => "mysql", + "pool" => 30 + }, + "login" => { + "username" => "user", + "password" => "password123" + }, + "development" => { + "adapter" => "mysql", + "pool" => 30, + "username" => "user", + "password" => "password123", + "host" => "localhost" + } + } + end + + it "correctly prefers explicitly defined values over default values from included sections" do + # Repeating this test 100 times to increase the likelihood of running into an issue caused by + # non-deterministic hash key enumeration. + 100.times do + result = YAML.safe_load <<-YAML + defaults: &defaults + foo: foo + bar: bar + baz: baz + custom: + <<: *defaults + bar: custom_bar + baz: custom_baz + YAML + + result["custom"].should == { + "foo" => "foo", + "bar" => "custom_bar", + "baz" => "custom_baz" + } + end + end + + it "works with multi-level inheritance" do + result = YAML.safe_load <<-YAML + defaults: &defaults + foo: foo + bar: bar + baz: baz + custom: &custom + <<: *defaults + bar: custom_bar + baz: custom_baz + grandcustom: &grandcustom + <<: *custom + YAML + + result.should == { + "defaults" => { "foo" => "foo", "bar" => "bar", "baz" => "baz" }, + "custom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" }, + "grandcustom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" } + } + end + + it "returns false when parsing an empty document" do + result = YAML.safe_load "" + result.should == false + end + + context "with custom initializers defined" do + before :each do + if SafeYAML::YAML_ENGINE == "psych" + SafeYAML::OPTIONS[:custom_initializers] = { + "!set" => lambda { Set.new }, + "!hashiemash" => lambda { Hashie::Mash.new } + } + else + SafeYAML::OPTIONS[:custom_initializers] = { + "tag:yaml.org,2002:set" => lambda { Set.new }, + "tag:yaml.org,2002:hashiemash" => lambda { Hashie::Mash.new } + } + end + end + + it "will use a custom initializer to instantiate an array-like class upon deserialization" do + result = YAML.safe_load <<-YAML.unindent + --- !set + - 1 + - 2 + - 3 + YAML + + result.should be_a(Set) + result.to_a.should =~ [1, 2, 3] + end + + it "will use a custom initializer to instantiate a hash-like class upon deserialization" do + result = YAML.safe_load <<-YAML.unindent + --- !hashiemash + foo: bar + YAML + + result.should be_a(Hashie::Mash) + result.to_hash.should == { "foo" => "bar" } + end + end + + context "with special whitelisted tags defined" do + before :each do + SafeYAML::whitelist!(OpenStruct) + + # Necessary for deserializing OpenStructs properly. + SafeYAML::OPTIONS[:deserialize_symbols] = true + end + + it "will allow objects to be deserialized for whitelisted tags" do + result = YAML.safe_load("--- !ruby/object:OpenStruct\ntable:\n foo: bar\n") + result.should be_a(OpenStruct) + result.instance_variable_get(:@table).should == { "foo" => "bar" } + end + + it "will not deserialize objects without whitelisted tags" do + result = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n") + result.should_not be_a(ExploitableBackDoor) + result.should == { "foo" => "bar" } + end + + it "will not allow non-whitelisted objects to be embedded within objects with whitelisted tags" do + result = YAML.safe_load <<-YAML.unindent + --- !ruby/object:OpenStruct + table: + :backdoor: !ruby/object:ExploitableBackDoor + foo: bar + YAML + + result.should be_a(OpenStruct) + result.backdoor.should_not be_a(ExploitableBackDoor) + result.backdoor.should == { "foo" => "bar" } + end + + context "with the :raise_on_unknown_tag option enabled" do + before :each do + SafeYAML::OPTIONS[:raise_on_unknown_tag] = true + end + + after :each do + SafeYAML.restore_defaults! + end + + it "raises an exception if a non-nil, non-whitelisted tag is encountered" do + lambda { + YAML.safe_load <<-YAML.unindent + --- !ruby/object:Unknown + foo: bar + YAML + }.should raise_error + end + + it "checks all tags, even those within objects with trusted tags" do + lambda { + YAML.safe_load <<-YAML.unindent + --- !ruby/object:OpenStruct + table: + :backdoor: !ruby/object:Unknown + foo: bar + YAML + }.should raise_error + end + + it "does not raise an exception as long as all tags are whitelisted" do + result = YAML.safe_load <<-YAML.unindent + --- !ruby/object:OpenStruct + table: + :backdoor: + string: foo + integer: 1 + float: 3.14 + symbol: :bar + date: 2013-02-20 + array: [] + hash: {} + YAML + + result.should be_a(OpenStruct) + result.backdoor.should == { + "string" => "foo", + "integer" => 1, + "float" => 3.14, + "symbol" => :bar, + "date" => Date.parse("2013-02-20"), + "array" => [], + "hash" => {} + } + end + + it "does not raise an exception on the non-specific '!' tag" do + result = nil + expect { result = YAML.safe_load "--- ! 'foo'" }.to_not raise_error + result.should == "foo" + end + + context "with whitelisted custom class" do + class SomeClass + attr_accessor :foo + end + let(:instance) { SomeClass.new } + + before do + SafeYAML::whitelist!(SomeClass) + instance.foo = 'with trailing whitespace: ' + end + + it "does not raise an exception on the non-specific '!' tag" do + result = nil + expect { result = YAML.safe_load(instance.to_yaml) }.to_not raise_error + result.foo.should == 'with trailing whitespace: ' + end + end + end + end + + context "when options are passed direclty to #load which differ from the defaults" do + let(:default_options) { {} } + + before :each do + SafeYAML::OPTIONS.merge!(default_options) + end + + context "(for example, when symbol deserialization is enabled by default)" do + let(:default_options) { { :deserialize_symbols => true } } + + it "goes with the default option when it is not overridden" do + silence_warnings do + YAML.load(":foo: bar").should == { :foo => "bar" } + end + end + + it "allows the default option to be overridden on a per-call basis" do + silence_warnings do + YAML.load(":foo: bar", :deserialize_symbols => false).should == { ":foo" => "bar" } + YAML.load(":foo: bar", :deserialize_symbols => true).should == { :foo => "bar" } + end + end + end + + context "(or, for example, when certain tags are whitelisted)" do + let(:default_options) { + { + :deserialize_symbols => true, + :whitelisted_tags => SafeYAML::YAML_ENGINE == "psych" ? + ["!ruby/object:OpenStruct"] : + ["tag:ruby.yaml.org,2002:object:OpenStruct"] + } + } + + it "goes with the default option when it is not overridden" do + result = safe_load_round_trip(OpenStruct.new(:foo => "bar")) + result.should be_a(OpenStruct) + result.foo.should == "bar" + end + + it "allows the default option to be overridden on a per-call basis" do + result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :whitelisted_tags => []) + result.should == { "table" => { :foo => "bar" } } + + result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :deserialize_symbols => false, :whitelisted_tags => []) + result.should == { "table" => { ":foo" => "bar" } } + end + end + end + end + + describe "unsafe_load_file" do + if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3" + it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do + backdoor = YAML.unsafe_load_file "spec/exploit.1.9.3.yaml" + backdoor.should be_exploited_through_setter + end + end + + if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.2" + it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do + backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml" + backdoor.should be_exploited_through_init_with + end + end + + it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do + backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml" + backdoor.should be_exploited_through_ivars + end + end + + describe "safe_load_file" do + it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do + object = YAML.safe_load_file "spec/exploit.1.9.3.yaml" + object.should_not be_a(ExploitableBackDoor) + end + + it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do + object = YAML.safe_load_file "spec/exploit.1.9.2.yaml" + object.should_not be_a(ExploitableBackDoor) + end + end + + describe "load" do + let(:options) { {} } + + let (:arguments) { + if SafeYAML::MULTI_ARGUMENT_YAML_LOAD + ["foo: bar", nil, options] + else + ["foo: bar", options] + end + } + + context "as long as a :default_mode has been specified" do + it "doesn't issue a warning for safe mode, since an explicit mode has been set" do + SafeYAML::OPTIONS[:default_mode] = :safe + Kernel.should_not_receive(:warn) + YAML.load(*arguments) + end + + it "doesn't issue a warning for unsafe mode, since an explicit mode has been set" do + SafeYAML::OPTIONS[:default_mode] = :unsafe + Kernel.should_not_receive(:warn) + YAML.load(*arguments) + end + end + + context "when the :safe options is specified" do + let(:safe_mode) { true } + let(:options) { { :safe => safe_mode } } + + it "doesn't issue a warning" do + Kernel.should_not_receive(:warn) + YAML.load(*arguments) + end + + it "calls #safe_load if the :safe option is set to true" do + YAML.should_receive(:safe_load) + YAML.load(*arguments) + end + + context "when the :safe option is set to false" do + let(:safe_mode) { false } + + it "calls #unsafe_load if the :safe option is set to false" do + YAML.should_receive(:unsafe_load) + YAML.load(*arguments) + end + end + end + + it "issues a warning when the :safe option is omitted" do + silence_warnings do + Kernel.should_receive(:warn) + YAML.load(*arguments) + end + end + + it "only issues a warning once (to avoid spamming an app's output)" do + silence_warnings do + Kernel.should_receive(:warn).once + 2.times { YAML.load(*arguments) } + end + end + + it "defaults to safe mode if the :safe option is omitted" do + silence_warnings do + YAML.should_receive(:safe_load) + YAML.load(*arguments) + end + end + + context "with the default mode set to :unsafe" do + before :each do + SafeYAML::OPTIONS[:default_mode] = :unsafe + end + + it "defaults to unsafe mode if the :safe option is omitted" do + silence_warnings do + YAML.should_receive(:unsafe_load) + YAML.load(*arguments) + end + end + + it "calls #safe_load if the :safe option is set to true" do + YAML.should_receive(:safe_load) + YAML.load(*(arguments + [{ :safe => true }])) + end + end + end + + describe "load_file" do + let(:filename) { "spec/exploit.1.9.2.yaml" } # doesn't really matter + + it "issues a warning if the :safe option is omitted" do + silence_warnings do + Kernel.should_receive(:warn) + YAML.load_file(filename) + end + end + + it "doesn't issue a warning as long as the :safe option is specified" do + Kernel.should_not_receive(:warn) + YAML.load_file(filename, :safe => true) + end + + it "defaults to safe mode if the :safe option is omitted" do + silence_warnings do + YAML.should_receive(:safe_load_file) + YAML.load_file(filename) + end + end + + it "calls #safe_load_file if the :safe option is set to true" do + YAML.should_receive(:safe_load_file) + YAML.load_file(filename, :safe => true) + end + + it "calls #unsafe_load_file if the :safe option is set to false" do + YAML.should_receive(:unsafe_load_file) + YAML.load_file(filename, :safe => false) + end + + context "with arbitrary object deserialization enabled by default" do + before :each do + SafeYAML::OPTIONS[:default_mode] = :unsafe + end + + it "defaults to unsafe mode if the :safe option is omitted" do + silence_warnings do + YAML.should_receive(:unsafe_load_file) + YAML.load_file(filename) + end + end + + it "calls #safe_load if the :safe option is set to true" do + YAML.should_receive(:safe_load_file) + YAML.load_file(filename, :safe => true) + end + end + end + + describe "whitelist!" do + context "not a class" do + it "should raise" do + expect { SafeYAML::whitelist! :foo }.to raise_error(/not a Class/) + SafeYAML::OPTIONS[:whitelisted_tags].should be_empty + end + end + + context "anonymous class" do + it "should raise" do + expect { SafeYAML::whitelist! Class.new }.to raise_error(/cannot be anonymous/) + SafeYAML::OPTIONS[:whitelisted_tags].should be_empty + end + end + + context "with a Class as its argument" do + it "should configure correctly" do + expect { SafeYAML::whitelist! OpenStruct }.to_not raise_error + SafeYAML::OPTIONS[:whitelisted_tags].grep(/OpenStruct\Z/).should_not be_empty + end + + it "successfully deserializes the specified class" do + SafeYAML.whitelist!(OpenStruct) + + # necessary for properly assigning OpenStruct attributes + SafeYAML::OPTIONS[:deserialize_symbols] = true + + result = safe_load_round_trip(OpenStruct.new(:foo => "bar")) + result.should be_a(OpenStruct) + result.foo.should == "bar" + end + + it "works for ranges" do + SafeYAML.whitelist!(Range) + safe_load_round_trip(1..10).should == (1..10) + end + + it "works for regular expressions" do + SafeYAML.whitelist!(Regexp) + safe_load_round_trip(/foo/).should == /foo/ + end + + it "works for multiple classes" do + SafeYAML.whitelist!(Range, Regexp) + safe_load_round_trip([(1..10), /bar/]).should == [(1..10), /bar/] + end + + it "works for arbitrary Exception subclasses" do + class CustomException < Exception + attr_reader :custom_message + + def initialize(custom_message) + @custom_message = custom_message + end + end + + SafeYAML.whitelist!(CustomException) + + ex = safe_load_round_trip(CustomException.new("blah")) + ex.should be_a(CustomException) + ex.custom_message.should == "blah" + end + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/spec_helper.rb b/lib/puppet/vendor/safe_yaml/spec/spec_helper.rb new file mode 100644 index 000000000..17c849d08 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/spec_helper.rb @@ -0,0 +1,18 @@ +HERE = File.dirname(__FILE__) unless defined?(HERE) +ROOT = File.join(HERE, "..") unless defined?(ROOT) + +$LOAD_PATH << File.join(ROOT, "lib") +$LOAD_PATH << File.join(HERE, "support") + +require "yaml" +if ENV["YAMLER"] && defined?(YAML::ENGINE) + YAML::ENGINE.yamler = ENV["YAMLER"] + puts "Running specs in Ruby #{RUBY_VERSION} with '#{YAML::ENGINE.yamler}' YAML engine." +end + +require "safe_yaml" +require "ostruct" +require "hashie" +require "heredoc_unindent" + +require File.join(HERE, "resolver_specs") diff --git a/lib/puppet/vendor/safe_yaml/spec/support/exploitable_back_door.rb b/lib/puppet/vendor/safe_yaml/spec/support/exploitable_back_door.rb new file mode 100644 index 000000000..48754b463 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/support/exploitable_back_door.rb @@ -0,0 +1,29 @@ +class ExploitableBackDoor + def exploited? + @exploited_through_setter || @exploited_through_init_with || @exploited_through_ivars + end + + def exploited_through_setter? + @exploited_through_setter + end + + def exploited_through_init_with? + @exploited_through_init_with + end + + def exploited_through_ivars? + self.instance_variables.any? + end + + def init_with(command) + # Note: this is how bad this COULD be. + # system("#{command}") + @exploited_through_init_with = true + end + + def []=(command, arguments) + # Note: this is how bad this COULD be. + # system("#{command} #{arguments}") + @exploited_through_setter = true + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/syck_resolver_spec.rb b/lib/puppet/vendor/safe_yaml/spec/syck_resolver_spec.rb new file mode 100644 index 000000000..a9c542195 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/syck_resolver_spec.rb @@ -0,0 +1,10 @@ +require File.join(File.dirname(__FILE__), "spec_helper") + +if SafeYAML::YAML_ENGINE == "syck" + require "safe_yaml/syck_resolver" + + describe SafeYAML::SyckResolver do + include ResolverSpecs + let(:resolver) { SafeYAML::SyckResolver.new } + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/transform/base64_spec.rb b/lib/puppet/vendor/safe_yaml/spec/transform/base64_spec.rb new file mode 100644 index 000000000..da872fb1e --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/transform/base64_spec.rb @@ -0,0 +1,11 @@ +require File.join(File.dirname(__FILE__), "..", "spec_helper") + +describe SafeYAML::Transform do + it "should return the same encoding when decoding Base64" do + value = "c3VyZS4=" + decoded = SafeYAML::Transform.to_proper_type(value, false, "!binary") + + decoded.should == "sure." + decoded.encoding.should == value.encoding if decoded.respond_to?(:encoding) + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/transform/to_date_spec.rb b/lib/puppet/vendor/safe_yaml/spec/transform/to_date_spec.rb new file mode 100644 index 000000000..4c5429e6c --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/transform/to_date_spec.rb @@ -0,0 +1,34 @@ +require File.join(File.dirname(__FILE__), "..", "spec_helper") + +describe SafeYAML::Transform::ToDate do + it "returns true when the value matches a valid Date" do + subject.transform?("2013-01-01").should == [true, Date.parse("2013-01-01")] + end + + it "returns false when the value does not match a valid Date" do + subject.transform?("foobar").should be_false + end + + it "returns false when the value does not end with a Date" do + subject.transform?("2013-01-01\nNOT A DATE").should be_false + end + + it "returns false when the value does not begin with a Date" do + subject.transform?("NOT A DATE\n2013-01-01").should be_false + end + + it "correctly parses the remaining formats of the YAML spec" do + equivalent_values = [ + "2001-12-15T02:59:43.1Z", # canonical + "2001-12-14t21:59:43.10-05:00", # iso8601 + "2001-12-14 21:59:43.10 -5", # space separated + "2001-12-15 2:59:43.10" # no time zone (Z) + ] + + equivalent_values.each do |value| + success, result = subject.transform?(value) + success.should be_true + result.should == Time.utc(2001, 12, 15, 2, 59, 43, 100000) + end + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/transform/to_float_spec.rb b/lib/puppet/vendor/safe_yaml/spec/transform/to_float_spec.rb new file mode 100644 index 000000000..9f56685b5 --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/transform/to_float_spec.rb @@ -0,0 +1,42 @@ +require File.join(File.dirname(__FILE__), "..", "spec_helper") + +describe SafeYAML::Transform::ToFloat do + it "returns true when the value matches a valid Float" do + subject.transform?("20.00").should == [true, 20.0] + end + + it "returns false when the value does not match a valid Float" do + subject.transform?("foobar").should be_false + end + + it "returns false when the value spans multiple lines" do + subject.transform?("20.00\nNOT A FLOAT").should be_false + end + + it "correctly parses all formats in the YAML spec" do + # canonical + subject.transform?("6.8523015e+5").should == [true, 685230.15] + + # exponentioal + subject.transform?("685.230_15e+03").should == [true, 685230.15] + + # fixed + subject.transform?("685_230.15").should == [true, 685230.15] + + # sexagesimal + subject.transform?("190:20:30.15").should == [true, 685230.15] + + # infinity + subject.transform?("-.inf").should == [true, (-1.0 / 0.0)] + + # not a number + # NOTE: can't use == here since NaN != NaN + success, result = subject.transform?(".NaN") + success.should be_true; result.should be_nan + end + + # issue 29 + it "returns false for the string '.'" do + subject.transform?(".").should be_false + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/transform/to_integer_spec.rb b/lib/puppet/vendor/safe_yaml/spec/transform/to_integer_spec.rb new file mode 100644 index 000000000..8423417ca --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/transform/to_integer_spec.rb @@ -0,0 +1,59 @@ +require File.join(File.dirname(__FILE__), "..", "spec_helper") + +describe SafeYAML::Transform::ToInteger do + it "returns true when the value matches a valid Integer" do + subject.transform?("10").should == [true, 10] + end + + it "returns false when the value does not match a valid Integer" do + subject.transform?("foobar").should be_false + end + + it "returns false when the value spans multiple lines" do + subject.transform?("10\nNOT AN INTEGER").should be_false + end + + it "allows commas in the number" do + subject.transform?("1,000").should == [true, 1000] + end + + it "correctly parses numbers in octal format" do + subject.transform?("010").should == [true, 8] + end + + it "correctly parses numbers in hexadecimal format" do + subject.transform?("0x1FF").should == [true, 511] + end + + it "defaults to a string for a number that resembles octal format but is not" do + subject.transform?("09").should be_false + end + + it "correctly parses 0 in decimal" do + subject.transform?("0").should == [true, 0] + end + + it "defaults to a string for a number that resembles hexadecimal format but is not" do + subject.transform?("0x1G").should be_false + end + + it "correctly parses all formats in the YAML spec" do + # canonical + subject.transform?("685230").should == [true, 685230] + + # decimal + subject.transform?("+685_230").should == [true, 685230] + + # octal + subject.transform?("02472256").should == [true, 685230] + + # hexadecimal: + subject.transform?("0x_0A_74_AE").should == [true, 685230] + + # binary + subject.transform?("0b1010_0111_0100_1010_1110").should == [true, 685230] + + # sexagesimal + subject.transform?("190:20:30").should == [true, 685230] + end +end diff --git a/lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb b/lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb new file mode 100644 index 000000000..aaa33390c --- /dev/null +++ b/lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb @@ -0,0 +1,49 @@ +require File.join(File.dirname(__FILE__), "..", "spec_helper") + +describe SafeYAML::Transform::ToSymbol do + def with_symbol_deserialization_value(value) + symbol_deserialization_flag = SafeYAML::OPTIONS[:deserialize_symbols] + SafeYAML::OPTIONS[:deserialize_symbols] = value + + yield + + ensure + SafeYAML::OPTIONS[:deserialize_symbols] = symbol_deserialization_flag + end + + def with_symbol_deserialization(&block) + with_symbol_deserialization_value(true, &block) + end + + def without_symbol_deserialization(&block) + with_symbol_deserialization_value(false, &block) + end + + it "returns true when the value matches a valid Symbol" do + with_symbol_deserialization { subject.transform?(":foo")[0].should be_true } + end + + it "returns true when the value matches a valid String+Symbol" do + with_symbol_deserialization { subject.transform?(':"foo"')[0].should be_true } + end + + it "returns false when symbol deserialization is disabled" do + without_symbol_deserialization { subject.transform?(":foo").should be_false } + end + + it "returns false when the value does not match a valid Symbol" do + with_symbol_deserialization { subject.transform?("foo").should be_false } + end + + it "returns false when the symbol does not begin the line" do + with_symbol_deserialization do + subject.transform?("NOT A SYMBOL\n:foo").should be_false + end + end + + it "returns false when the symbol does not end the line" do + with_symbol_deserialization do + subject.transform?(":foo\nNOT A SYMBOL").should be_false + end + end +end diff --git a/lib/puppet/version.rb b/lib/puppet/version.rb index 62b5f064d..83658f148 100644 --- a/lib/puppet/version.rb +++ b/lib/puppet/version.rb @@ -6,7 +6,7 @@ # Raketasks and such to set the version based on the output of `git describe` # module Puppet - PUPPETVERSION = '2.7.21' + PUPPETVERSION = '2.7.23' def self.version @puppet_version || PUPPETVERSION diff --git a/spec/lib/puppet_spec/matchers.rb b/spec/lib/puppet_spec/matchers.rb index 77f580330..3960e4111 100644 --- a/spec/lib/puppet_spec/matchers.rb +++ b/spec/lib/puppet_spec/matchers.rb @@ -85,3 +85,11 @@ RSpec::Matchers.define :have_printed do |expected| diffable end + +RSpec::Matchers.define :equal_attributes_of do |expected| + match do |actual| + actual.instance_variables.all? do |attr| + actual.instance_variable_get(attr) == expected.instance_variable_get(attr) + end + end +end diff --git a/spec/unit/file_serving/metadata_spec.rb b/spec/unit/file_serving/metadata_spec.rb index 4edeb4f2d..fa870a2ee 100755 --- a/spec/unit/file_serving/metadata_spec.rb +++ b/spec/unit/file_serving/metadata_spec.rb @@ -33,14 +33,6 @@ describe Puppet::FileServing::Metadata do describe "when serializing" do let(:metadata) { Puppet::FileServing::Metadata.new(foobar) } - it "should perform pson serialization by calling to_pson on it's pson_data_hash" do - pdh = mock "data hash" - pdh_as_pson = mock "data as pson" - metadata.expects(:to_pson_data_hash).returns pdh - pdh.expects(:to_pson).returns pdh_as_pson - metadata.to_pson.should == pdh_as_pson - end - it "should serialize as FileMetadata" do metadata.to_pson_data_hash['document_type'].should == "FileMetadata" end @@ -49,48 +41,48 @@ describe Puppet::FileServing::Metadata do metadata.to_pson_data_hash['data'].keys.sort.should == %w{ path relative_path links owner group mode checksum type destination }.sort end - it "should pass the path in the hash verbatum" do - metadata.to_pson_data_hash['data']['path'] == metadata.path + it "should pass the path in the hash verbatim" do + metadata.to_pson_data_hash['data']['path'].should == metadata.path end - it "should pass the relative_path in the hash verbatum" do - metadata.to_pson_data_hash['data']['relative_path'] == metadata.relative_path + it "should pass the relative_path in the hash verbatim" do + metadata.to_pson_data_hash['data']['relative_path'].should == metadata.relative_path end - it "should pass the links in the hash verbatum" do - metadata.to_pson_data_hash['data']['links'] == metadata.links + it "should pass the links in the hash verbatim" do + metadata.to_pson_data_hash['data']['links'].should == metadata.links end - it "should pass the path owner in the hash verbatum" do - metadata.to_pson_data_hash['data']['owner'] == metadata.owner + it "should pass the path owner in the hash verbatim" do + metadata.to_pson_data_hash['data']['owner'].should == metadata.owner end - it "should pass the group in the hash verbatum" do - metadata.to_pson_data_hash['data']['group'] == metadata.group + it "should pass the group in the hash verbatim" do + metadata.to_pson_data_hash['data']['group'].should == metadata.group end - it "should pass the mode in the hash verbatum" do - metadata.to_pson_data_hash['data']['mode'] == metadata.mode + it "should pass the mode in the hash verbatim" do + metadata.to_pson_data_hash['data']['mode'].should == metadata.mode end - it "should pass the ftype in the hash verbatum as the 'type'" do - metadata.to_pson_data_hash['data']['type'] == metadata.ftype + it "should pass the ftype in the hash verbatim as the 'type'" do + metadata.to_pson_data_hash['data']['type'].should == metadata.ftype end - it "should pass the destination verbatum" do - metadata.to_pson_data_hash['data']['destination'] == metadata.destination + it "should pass the destination verbatim" do + metadata.to_pson_data_hash['data']['destination'].should == metadata.destination end it "should pass the checksum in the hash as a nested hash" do metadata.to_pson_data_hash['data']['checksum'].should be_is_a(Hash) end - it "should pass the checksum_type in the hash verbatum as the checksum's type" do - metadata.to_pson_data_hash['data']['checksum']['type'] == metadata.checksum_type + it "should pass the checksum_type in the hash verbatim as the checksum's type" do + metadata.to_pson_data_hash['data']['checksum']['type'].should == metadata.checksum_type end - it "should pass the checksum in the hash verbatum as the checksum's value" do - metadata.to_pson_data_hash['data']['checksum']['value'] == metadata.checksum + it "should pass the checksum in the hash verbatim as the checksum's value" do + metadata.to_pson_data_hash['data']['checksum']['value'].should == metadata.checksum end end diff --git a/spec/unit/file_system/path_pattern_spec.rb b/spec/unit/file_system/path_pattern_spec.rb new file mode 100644 index 000000000..67c23692b --- /dev/null +++ b/spec/unit/file_system/path_pattern_spec.rb @@ -0,0 +1,139 @@ +require 'spec_helper' +require 'puppet_spec/files' +require 'puppet/file_system' + +describe Puppet::FileSystem::PathPattern do + include PuppetSpec::Files + InvalidPattern = Puppet::FileSystem::PathPattern::InvalidPattern + + describe 'relative' do + it "can not be created with a traversal up the directory tree" do + expect do + Puppet::FileSystem::PathPattern.relative("my/../other") + end.to raise_error(InvalidPattern, "PathPatterns cannot be created with directory traversals.") + end + + it "can be created with a '..' prefixing a filename" do + Puppet::FileSystem::PathPattern.relative("my/..other").to_s.should eq("my/..other") + end + + it "can be created with a '..' suffixing a filename" do + Puppet::FileSystem::PathPattern.relative("my/other..").to_s.should eq("my/other..") + end + + it "can be created with a '..' embedded in a filename" do + Puppet::FileSystem::PathPattern.relative("my/ot..her").to_s.should eq("my/ot..her") + end + + it "can not be created with a \\0 byte embedded" do + expect do + Puppet::FileSystem::PathPattern.relative("my/\0/other") + end.to raise_error(InvalidPattern, /PathPatterns cannot be created with a zero byte./) + end + + it "can not be created with a windows drive" do + expect do + Puppet::FileSystem::PathPattern.relative("c:\\relative\\path") + end.to raise_error(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.") + end + + it "can not be created with a windows drive (with space)" do + expect do + Puppet::FileSystem::PathPattern.relative(" c:\\relative\\path") + end.to raise_error(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.") + end + + it "can not create an absolute relative path" do + expect do + Puppet::FileSystem::PathPattern.relative("/no/absolutes") + end.to raise_error(InvalidPattern, "A relative PathPattern cannot be an absolute path.") + end + + it "can not create an absolute relative path (with space)" do + expect do + Puppet::FileSystem::PathPattern.relative("\t/no/absolutes") + end.to raise_error(InvalidPattern, "A relative PathPattern cannot be an absolute path.") + end + + it "can not create a relative path that is a windows path relative to the current drive" do + expect do + Puppet::FileSystem::PathPattern.relative("\\no\relatives") + end.to raise_error(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.") + end + + it "creates a relative PathPattern from a valid relative path" do + Puppet::FileSystem::PathPattern.relative("a/relative/path").to_s.should eq("a/relative/path") + end + + it "is not absolute" do + Puppet::FileSystem::PathPattern.relative("a/relative/path").should_not be_absolute + end + end + + describe 'absolute' do + it "can not create a relative absolute path" do + expect do + Puppet::FileSystem::PathPattern.absolute("no/relatives") + end.to raise_error(InvalidPattern, "An absolute PathPattern cannot be a relative path.") + end + + it "can not create an absolute path that is a windows path relative to the current drive" do + expect do + Puppet::FileSystem::PathPattern.absolute("\\no\\relatives") + end.to raise_error(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.") + end + + it "creates an absolute PathPattern from a valid absolute path" do + Puppet::FileSystem::PathPattern.absolute("/an/absolute/path").to_s.should eq("/an/absolute/path") + end + + it "creates an absolute PathPattern from a valid Windows absolute path" do + Puppet::FileSystem::PathPattern.absolute("c:/absolute/windows/path").to_s.should eq("c:/absolute/windows/path") + end + + it "is absolute" do + Puppet::FileSystem::PathPattern.absolute("c:/absolute/windows/path").should be_absolute + end + + it "can be created with a '..' embedded in a filename on windows", :if => Puppet.features.microsoft_windows? do + Puppet::FileSystem::PathPattern.absolute(%q{c:\..my\ot..her\one..}).to_s.should eq(%q{c:\..my\ot..her\one..}) + end + end + + it "prefixes the relative path pattern with another path" do + pattern = Puppet::FileSystem::PathPattern.relative("docs/*_thoughts.txt") + prefix = Puppet::FileSystem::PathPattern.absolute("/prefix") + + absolute_pattern = pattern.prefix_with(prefix) + + absolute_pattern.should be_absolute + absolute_pattern.to_s.should eq(File.join("/prefix", "docs/*_thoughts.txt")) + end + + it "refuses to prefix with a relative pattern" do + pattern = Puppet::FileSystem::PathPattern.relative("docs/*_thoughts.txt") + prefix = Puppet::FileSystem::PathPattern.relative("prefix") + + expect do + pattern.prefix_with(prefix) + end.to raise_error(InvalidPattern, "An absolute PathPattern cannot be a relative path.") + end + + it "applies the pattern to the filesystem as a glob" do + dir = tmpdir('globtest') + create_file_in(dir, "found_one") + create_file_in(dir, "found_two") + create_file_in(dir, "third_not_found") + + pattern = Puppet::FileSystem::PathPattern.relative("found_*").prefix_with( + Puppet::FileSystem::PathPattern.absolute(dir)) + + pattern.glob.should include(File.join(dir, "found_one")) + pattern.glob.should include(File.join(dir, "found_two")) + pattern.glob.should_not include(File.join(dir, "third_not_found")) + end + + def create_file_in(dir, name) + File.open(File.join(dir, name), "w") { |f| f.puts "data" } + end +end diff --git a/spec/unit/indirector/report/rest_spec.rb b/spec/unit/indirector/report/rest_spec.rb index 806ae6efd..4c45fceb1 100755 --- a/spec/unit/indirector/report/rest_spec.rb +++ b/spec/unit/indirector/report/rest_spec.rb @@ -24,4 +24,45 @@ describe Puppet::Transaction::Report::Rest do Puppet::Transaction::Report::Rest.server.should_not be_nil Puppet::Transaction::Report::Rest.port.should_not be_nil end + + let(:model) { Puppet::Transaction::Report } + let(:terminus_class) { Puppet::Transaction::Report::Rest } + let(:terminus) { model.indirection.terminus(:rest) } + let(:indirection) { model.indirection } + + before(:each) do + Puppet::Transaction::Report.indirection.terminus_class = :rest + end + + def mock_response(code, body, content_type='text/plain', encoding=nil) + obj = stub('http 200 ok', :code => code.to_s, :body => body) + obj.stubs(:[]).with('content-type').returns(content_type) + obj.stubs(:[]).with('content-encoding').returns(encoding) + obj + end + + def save_request(key, instance) + Puppet::Indirector::Request.new(:report, :find, key, instance) + end + + describe "#save" do + let(:http_method) { :put } + let(:response) { mock_response(200, 'body') } + let(:connection) { stub('mock http connection', :put => response, :verify_callback= => nil) } + let(:instance) { model.new('the thing', 'some contents') } + let(:request) { save_request(instance.name, instance) } + + before :each do + terminus.stubs(:network).returns(connection) + end + + it "deserializes the response as an array of report processor names" do + processors = ["store", "http"] + body = YAML.dump(processors) + response = mock_response('200', body, 'text/yaml') + connection.expects(:put).returns response + + terminus.save(request).should == ["store", "http"] + end + end end diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb index 7954baaed..b7d233264 100755 --- a/spec/unit/indirector/rest_spec.rb +++ b/spec/unit/indirector/rest_spec.rb @@ -1,57 +1,140 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'puppet/indirector' +require 'puppet/indirector/errors' require 'puppet/indirector/rest' -shared_examples_for "a REST http call" do - it "should accept a path" do - lambda { @search.send(@method, *@arguments) }.should_not raise_error(ArgumentError) - end +# Just one from each category since the code makes no real distinctions +HTTP_ERROR_CODES = [300, 400, 500] +shared_examples_for "a REST terminus method" do |terminus_method| + HTTP_ERROR_CODES.each do |code| + describe "when the response code is #{code}" do + let(:response) { mock_response(code, 'error messaged!!!') } + + it "raises an http error with the body of the response" do + expect { + terminus.send(terminus_method, request) + }.to raise_error(Net::HTTPError, "Error #{code} on SERVER: #{response.body}") + end + + it "does not attempt to deserialize the response" do + model.expects(:convert_from).never + + expect { + terminus.send(terminus_method, request) + }.to raise_error(Net::HTTPError) + end + + # I'm not sure what this means or if it's used + it "if the body is empty raises an http error with the response header" do + response.stubs(:body).returns "" + response.stubs(:message).returns "fhqwhgads" + + expect { + terminus.send(terminus_method, request) + }.to raise_error(Net::HTTPError, "Error #{code} on SERVER: #{response.message}") + end - it "should require a path" do - lambda { @searcher.send(@method) }.should raise_error(ArgumentError) + describe "and the body is compressed" do + it "raises an http error with the decompressed body of the response" do + uncompressed_body = "why" + compressed_body = Zlib::Deflate.deflate(uncompressed_body) + + response = mock_response(code, compressed_body, 'text/plain', 'deflate') + connection.expects(http_method).returns(response) + + expect { + terminus.send(terminus_method, request) + }.to raise_error(Net::HTTPError, "Error #{code} on SERVER: #{uncompressed_body}") + end + end + end end +end - it "should return the results of deserializing the response to the request" do - conn = mock 'connection' - conn.stubs(:put).returns @response - conn.stubs(:delete).returns @response - conn.stubs(:get).returns @response - Puppet::Network::HttpPool.stubs(:http_instance).returns conn +shared_examples_for "a deserializing terminus method" do |terminus_method| + describe "when the response has no content-type" do + let(:response) { mock_response(200, "body", nil, nil) } + it "raises an error" do + expect { + terminus.send(terminus_method, request) + }.to raise_error(RuntimeError, "No content type in http response; cannot parse") + end + end - @searcher.expects(:deserialize).with(@response).returns "myobject" + it "doesn't catch errors in deserialization" do + model.expects(:convert_from).raises(Puppet::Error, "Whoa there") - @searcher.send(@method, *@arguments).should == 'myobject' + expect { terminus.send(terminus_method, request) }.to raise_error(Puppet::Error, "Whoa there") end end describe Puppet::Indirector::REST do before :all do - Puppet::Indirector::Terminus.stubs(:register_terminus_class) - @model = stub('model', :supported_formats => %w{}, :convert_from => nil) - @instance = stub('model instance', :name= => nil) - @indirection = stub('indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model) - Puppet::Indirector::Indirection.expects(:instance).returns(@indirection) - - module This - module Is - module A - module Test - end - end + class Puppet::TestModel + extend Puppet::Indirector + indirects :test_model + attr_accessor :name, :data + def initialize(name = "name", data = '') + @name = name + @data = data + end + + def self.convert_from(format, string) + new('', string) + end + + def self.convert_from_multiple(format, string) + string.split(',').collect { |s| convert_from(format, s) } + end + + def ==(other) + other.is_a? Puppet::TestModel and other.name == name and other.data == data end end - @rest_class = class This::Is::A::Test::Class < Puppet::Indirector::REST - self + + # The subclass must not be all caps even though the superclass is + class Puppet::TestModel::Rest < Puppet::Indirector::REST end + + Puppet::TestModel.indirection.terminus_class = :rest + end + + after :all do + # Remove the class, unlinking it from the rest of the system. + Puppet.send(:remove_const, :TestModel) + end + + let(:terminus_class) { Puppet::TestModel::Rest } + let(:terminus) { Puppet::TestModel.indirection.terminus(:rest) } + let(:indirection) { Puppet::TestModel.indirection } + let(:model) { Puppet::TestModel } + + def mock_response(code, body, content_type='text/plain', encoding=nil) + obj = stub('http 200 ok', :code => code.to_s, :body => body) + obj.stubs(:[]).with('content-type').returns(content_type) + obj.stubs(:[]).with('content-encoding').returns(encoding) + obj + end + + def find_request(key, options={}) + Puppet::Indirector::Request.new(:test_model, :find, key, options) + end + + def head_request(key, options={}) + Puppet::Indirector::Request.new(:test_model, :head, key, options) + end + + def search_request(key, options={}) + Puppet::Indirector::Request.new(:test_model, :search, key, options) end - before :each do - @response = stub('mock response', :body => 'result', :code => "200") - @response.stubs(:[]).with('content-type').returns "text/plain" - @response.stubs(:[]).with('content-encoding').returns nil + def delete_request(key, options={}) + Puppet::Indirector::Request.new(:test_model, :destroy, key, options) + end - @searcher = @rest_class.new - @searcher.stubs(:model).returns @model + def save_request(key, instance) + Puppet::Indirector::Request.new(:test_model, :save, key, instance) end it "should include the v1 REST API module" do @@ -59,35 +142,35 @@ describe Puppet::Indirector::REST do end it "should have a method for specifying what setting a subclass should use to retrieve its server" do - @rest_class.should respond_to(:use_server_setting) + terminus_class.should respond_to(:use_server_setting) end it "should use any specified setting to pick the server" do - @rest_class.expects(:server_setting).returns :servset - Puppet.settings.expects(:value).with(:servset).returns "myserver" - @rest_class.server.should == "myserver" + terminus_class.expects(:server_setting).returns :inventory_server + Puppet[:inventory_server] = "myserver" + terminus_class.server.should == "myserver" end it "should default to :server for the server setting" do - @rest_class.expects(:server_setting).returns nil - Puppet.settings.expects(:value).with(:server).returns "myserver" - @rest_class.server.should == "myserver" + terminus_class.expects(:server_setting).returns nil + Puppet[:server] = "myserver" + terminus_class.server.should == "myserver" end it "should have a method for specifying what setting a subclass should use to retrieve its port" do - @rest_class.should respond_to(:use_port_setting) + terminus_class.should respond_to(:use_port_setting) end it "should use any specified setting to pick the port" do - @rest_class.expects(:port_setting).returns :servset - Puppet.settings.expects(:value).with(:servset).returns "321" - @rest_class.port.should == 321 + terminus_class.expects(:port_setting).returns :ca_port + Puppet[:ca_port] = "321" + terminus_class.port.should == 321 end it "should default to :port for the port setting" do - @rest_class.expects(:port_setting).returns nil - Puppet.settings.expects(:value).with(:masterport).returns "543" - @rest_class.port.should == 543 + terminus_class.expects(:port_setting).returns nil + Puppet[:masterport] = "543" + terminus_class.port.should == 543 end describe "when making http requests" do @@ -112,24 +195,24 @@ describe Puppet::Indirector::REST do 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). + terminus.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')) + terminus.http_request(:get, stub('request')) 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 - @searcher.stubs(:network). + terminus.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')) }. + expect { terminus.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] @@ -138,115 +221,16 @@ describe Puppet::Indirector::REST do it "should pass along the error message otherwise" do connection = Net::HTTP.new('my_server', 8140) - @searcher.stubs(:network).returns(connection) + terminus.stubs(:network).returns(connection) connection.stubs(:get).raises(OpenSSL::SSL::SSLError.new('some other message')) expect do - @searcher.http_request(:get, stub('request')) + terminus.http_request(:get, stub('request')) end.to raise_error(/some other message/) end end - describe "when deserializing responses" do - it "should return nil if the response code is 404" do - response = mock 'response' - response.expects(:code).returns "404" - - @searcher.deserialize(response).should be_nil - end - - [300,400,403,405,500,501,502,503,504].each { |rc| - describe "when the response code is #{rc}" do - before :each do - @model.expects(:convert_from).never - - @response = mock 'response' - @response.stubs(:code).returns rc.to_s - @response.stubs(:[]).with('content-encoding').returns nil - @response.stubs(:message).returns "There was a problem (header)" - end - - it "should fail" do - @response.stubs(:body).returns nil - lambda { @searcher.deserialize(@response) }.should raise_error(Net::HTTPError) - end - - it "should take the error message from the body, if present" do - @response.stubs(:body).returns "There was a problem (body)" - lambda { @searcher.deserialize(@response) }.should raise_error(Net::HTTPError,"Error #{rc} on SERVER: There was a problem (body)") - end - - it "should take the error message from the response header if the body is empty" do - @response.stubs(:body).returns "" - lambda { @searcher.deserialize(@response) }.should raise_error(Net::HTTPError,"Error #{rc} on SERVER: There was a problem (header)") - end - - it "should take the error message from the response header if the body is absent" do - @response.stubs(:body).returns nil - lambda { @searcher.deserialize(@response) }.should raise_error(Net::HTTPError,"Error #{rc} on SERVER: There was a problem (header)") - end - - describe "and with http compression" do - it "should uncompress the body" do - @response.stubs(:body).returns("compressed body") - @searcher.expects(:uncompress_body).with(@response).returns("uncompressed") - lambda { @searcher.deserialize(@response) }.should raise_error { |e| e.message =~ /uncompressed/ } - end - end - end - } - - it "should return the results of converting from the format specified by the content-type header if the response code is in the 200s" do - @model.expects(:convert_from).with("myformat", "mydata").returns "myobject" - - response = mock 'response' - response.stubs(:[]).with("content-type").returns "myformat" - response.stubs(:[]).with("content-encoding").returns nil - response.stubs(:body).returns "mydata" - response.stubs(:code).returns "200" - - @searcher.deserialize(response).should == "myobject" - end - - it "should convert and return multiple instances if the return code is in the 200s and 'multiple' is specified" do - @model.expects(:convert_from_multiple).with("myformat", "mydata").returns "myobjects" - - response = mock 'response' - response.stubs(:[]).with("content-type").returns "myformat" - response.stubs(:[]).with("content-encoding").returns nil - response.stubs(:body).returns "mydata" - response.stubs(:code).returns "200" - - @searcher.deserialize(response, true).should == "myobjects" - end - - it "should strip the content-type header to keep only the mime-type" do - @model.expects(:convert_from).with("text/plain", "mydata").returns "myobject" - - response = mock 'response' - response.stubs(:[]).with("content-type").returns "text/plain; charset=utf-8" - response.stubs(:[]).with("content-encoding").returns nil - response.stubs(:body).returns "mydata" - response.stubs(:code).returns "200" - - @searcher.deserialize(response) - end - - it "should uncompress the body" do - @model.expects(:convert_from).with("myformat", "uncompressed mydata").returns "myobject" - - response = mock 'response' - response.stubs(:[]).with("content-type").returns "myformat" - response.stubs(:body).returns "compressed mydata" - response.stubs(:code).returns "200" - - @searcher.expects(:uncompress_body).with(response).returns("uncompressed mydata") - - @searcher.deserialize(response).should == "myobject" - end - end - describe "when creating an HTTP client" do before do Puppet.settings.stubs(:value).returns("rest_testing") @@ -254,38 +238,42 @@ describe Puppet::Indirector::REST do it "should use the class's server and port if the indirection request provides neither" do @request = stub 'request', :key => "foo", :server => nil, :port => nil - @searcher.class.expects(:port).returns 321 - @searcher.class.expects(:server).returns "myserver" + terminus.class.expects(:port).returns 321 + terminus.class.expects(:server).returns "myserver" Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn" - @searcher.network(@request).should == "myconn" + terminus.network(@request).should == "myconn" end it "should use the server from the indirection request if one is present" do @request = stub 'request', :key => "foo", :server => "myserver", :port => nil - @searcher.class.stubs(:port).returns 321 + terminus.class.stubs(:port).returns 321 Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn" - @searcher.network(@request).should == "myconn" + terminus.network(@request).should == "myconn" end it "should use the port from the indirection request if one is present" do @request = stub 'request', :key => "foo", :server => nil, :port => 321 - @searcher.class.stubs(:server).returns "myserver" + terminus.class.stubs(:server).returns "myserver" Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn" - @searcher.network(@request).should == "myconn" + terminus.network(@request).should == "myconn" end end - describe "when doing a find" do - before :each do - @connection = stub('mock http connection', :get => @response, :verify_callback= => nil) - @searcher.stubs(:network).returns(@connection) # neuter the network connection + describe "#find" do + let(:http_method) { :get } + let(:response) { mock_response(200, 'body') } + let(:connection) { stub('mock http connection', :get => response, :verify_callback= => nil) } + let(:request) { find_request('foo') } - # Use a key with spaces, so we can test escaping - @request = Puppet::Indirector::Request.new(:foo, :find, "foo bar", :environment => "myenv") + before :each do + terminus.stubs(:network).returns(connection) end - describe "with a large body" do - it "should use the POST http method" do + it_behaves_like 'a REST terminus method', :find + it_behaves_like 'a deserializing terminus method', :find + + describe "with a long set of parameters" do + it "calls post on the connection with the query params in the body" do params = {} 'aa'.upto('zz') do |s| params[s] = 'foo' @@ -296,283 +284,270 @@ describe Puppet::Indirector::REST do # to avoid a failure. params.delete('ip') - @request = Puppet::Indirector::Request.new(:foo, :find, "foo bar", params.merge(:environment => "myenv")) + request = find_request('whoa', params) - @connection.expects(:post).with do |uri, body| - uri == "/myenv/foo/foo%20bar" and body.split("&").sort == params.map {|key,value| "#{key}=#{value}"}.sort - end.returns(@response) + connection.expects(:post).with do |uri, body| + body.split("&").sort == params.map {|key,value| "#{key}=#{value}"}.sort + end.returns(mock_response(200, 'body')) - @searcher.find(@request) + terminus.find(request) end end - describe "with a small body" do - it "should use the GET http method" do - @searcher.expects(:network).returns @connection - @connection.expects(:get).returns @response - @searcher.find(@request) + describe "with no parameters" do + it "calls get on the connection" do + request = find_request('foo bar') + + connection.expects(:get).with('/production/test_model/foo%20bar?', anything).returns(mock_response('200', 'response body')) + + terminus.find(request).should == model.new('foo bar', 'response body') end end - it "should deserialize and return the http response, setting name" do - @connection.expects(:get).returns @response + it "returns nil on 404" do + response = mock_response('404', nil) - instance = stub 'object' - instance.expects(:name=) - @searcher.expects(:deserialize).with(@response).returns instance + connection.expects(:get).returns(response) - @searcher.find(@request).should == instance + terminus.find(request).should == nil end - it "should deserialize and return the http response, and not require name=" do - @connection.expects(:get).returns @response + it "asks the model to deserialize the response body and sets the name on the resulting object to the find key" do + connection.expects(:get).returns response - instance = stub 'object' - @searcher.expects(:deserialize).with(@response).returns instance + model.expects(:convert_from).with(response['content-type'], response.body).returns( + model.new('overwritten', 'decoded body') + ) - @searcher.find(@request).should == instance + terminus.find(request).should == model.new('foo', 'decoded body') end - it "should use the URI generated by the Handler module" do - @connection.expects(:get).with { |path, args| path == "/myenv/foo/foo%20bar?" }.returns(@response) - @searcher.find(@request) - end + it "doesn't require the model to support name=" do + connection.expects(:get).returns response + instance = model.new('name', 'decoded body') - it "should provide an Accept header containing the list of supported formats joined with commas" do - @connection.expects(:get).with { |path, args| args["Accept"] == "supported, formats" }.returns(@response) + model.expects(:convert_from).with(response['content-type'], response.body).returns(instance) + instance.expects(:respond_to?).with(:name=).returns(false) + instance.expects(:name=).never - @searcher.model.expects(:supported_formats).returns %w{supported formats} - @searcher.find(@request) + terminus.find(request).should == model.new('name', 'decoded body') end - it "should add Accept-Encoding header" do - @searcher.expects(:add_accept_encoding).returns({"accept-encoding" => "gzip"}) + it "provides an Accept header containing the list of supported formats joined with commas" do + connection.expects(:get).with(anything, has_entry("Accept" => "supported, formats")).returns(response) - @connection.expects(:get).with { |path, args| args["accept-encoding"] == "gzip" }.returns(@response) - @searcher.find(@request) + terminus.model.expects(:supported_formats).returns %w{supported formats} + terminus.find(request) end - it "should deserialize and return the network response" do - @searcher.expects(:deserialize).with(@response).returns @instance - @searcher.find(@request).should equal(@instance) - end + it "adds an Accept-Encoding header" do + terminus.expects(:add_accept_encoding).returns({"accept-encoding" => "gzip"}) - it "should set the name of the resulting instance to the asked-for name" do - @searcher.expects(:deserialize).with(@response).returns @instance - @instance.expects(:name=).with "foo bar" - @searcher.find(@request) - end + connection.expects(:get).with(anything, has_entry("accept-encoding" => "gzip")).returns(response) - it "should generate an error when result data deserializes fails" do - @searcher.expects(:deserialize).raises(ArgumentError) - lambda { @searcher.find(@request) }.should raise_error(ArgumentError) + terminus.find(request) end - end - describe "when doing a head" do - before :each do - @connection = stub('mock http connection', :head => @response, :verify_callback= => nil) - @searcher.stubs(:network).returns(@connection) + it "uses only the mime-type from the content-type header when asking the model to deserialize" do + response = mock_response('200', 'mydata', "text/plain; charset=utf-8") + connection.expects(:get).returns(response) + + model.expects(:convert_from).with("text/plain", "mydata").returns "myobject" - # Use a key with spaces, so we can test escaping - @request = Puppet::Indirector::Request.new(:foo, :head, "foo bar") + terminus.find(request).should == "myobject" end - it "should call the HEAD http method on a network connection" do - @searcher.expects(:network).returns @connection - @connection.expects(:head).returns @response - @searcher.head(@request) + it "decompresses the body before passing it to the model for deserialization" do + uncompressed_body = "Why hello there" + compressed_body = Zlib::Deflate.deflate(uncompressed_body) + + response = mock_response('200', compressed_body, 'text/plain', 'deflate') + connection.expects(:get).returns(response) + + model.expects(:convert_from).with("text/plain", uncompressed_body).returns "myobject" + + terminus.find(request).should == "myobject" end + end - it "should return true if there was a successful http response" do - @connection.expects(:head).returns @response - @response.stubs(:code).returns "200" + describe "#head" do + let(:http_method) { :head } + let(:response) { mock_response(200, nil) } + let(:connection) { stub('mock http connection', :head => response, :verify_callback= => nil) } + let(:request) { head_request('foo') } - @searcher.head(@request).should == true + before :each do + terminus.stubs(:network).returns(connection) end - it "should return false if there was a successful http response" do - @connection.expects(:head).returns @response - @response.stubs(:code).returns "404" + it_behaves_like 'a REST terminus method', :head + + it "returns true if there was a successful http response" do + connection.expects(:head).returns mock_response('200', nil) - @searcher.head(@request).should == false + terminus.head(request).should == true end - it "should use the URI generated by the Handler module" do - @searcher.expects(:indirection2uri).with(@request).returns "/my/uri" - @connection.expects(:head).with { |path, args| path == "/my/uri" }.returns(@response) - @searcher.head(@request) + it "returns false on a 404 response" do + connection.expects(:head).returns mock_response('404', nil) + + terminus.head(request).should == false end end - describe "when doing a search" do - before :each do - @connection = stub('mock http connection', :get => @response, :verify_callback= => nil) - @searcher.stubs(:network).returns(@connection) # neuter the network connection - - @model.stubs(:convert_from_multiple) + describe "#search" do + let(:http_method) { :get } + let(:response) { mock_response(200, 'data1,data2,data3') } + let(:connection) { stub('mock http connection', :get => response, :verify_callback= => nil) } + let(:request) { search_request('foo') } - @request = Puppet::Indirector::Request.new(:foo, :search, "foo bar") + before :each do + terminus.stubs(:network).returns(connection) end + it_behaves_like 'a REST terminus method', :search + it_behaves_like 'a deserializing terminus method', :search + it "should call the GET http method on a network connection" do - @searcher.expects(:network).returns @connection - @connection.expects(:get).returns @response - @searcher.search(@request) + connection.expects(:get).with('/production/test_models/foo', has_key('Accept')).returns mock_response(200, 'data3, data4') + + terminus.search(request) end - it "should deserialize as multiple instances and return the http response" do - @connection.expects(:get).returns @response - @searcher.expects(:deserialize).with(@response, true).returns "myobject" + it "returns an empty list on 404" do + response = mock_response('404', nil) + + connection.expects(:get).returns(response) - @searcher.search(@request).should == 'myobject' + terminus.search(request).should == [] end - it "should use the URI generated by the Handler module" do - @searcher.expects(:indirection2uri).with(@request).returns "/mys/uri" - @connection.expects(:get).with { |path, args| path == "/mys/uri" }.returns(@response) - @searcher.search(@request) + it "asks the model to deserialize the response body into multiple instances" do + terminus.search(request).should == [model.new('', 'data1'), model.new('', 'data2'), model.new('', 'data3')] end it "should provide an Accept header containing the list of supported formats joined with commas" do - @connection.expects(:get).with { |path, args| args["Accept"] == "supported, formats" }.returns(@response) + connection.expects(:get).with(anything, has_entry("Accept" => "supported, formats")).returns(mock_response(200, '')) - @searcher.model.expects(:supported_formats).returns %w{supported formats} - @searcher.search(@request) + terminus.model.expects(:supported_formats).returns %w{supported formats} + terminus.search(request) end it "should return an empty array if serialization returns nil" do - @model.stubs(:convert_from_multiple).returns nil + model.stubs(:convert_from_multiple).returns nil - @searcher.search(@request).should == [] - end - - it "should generate an error when result data deserializes fails" do - @searcher.expects(:deserialize).raises(ArgumentError) - lambda { @searcher.search(@request) }.should raise_error(ArgumentError) + terminus.search(request).should == [] end end - describe "when doing a destroy" do - before :each do - @connection = stub('mock http connection', :delete => @response, :verify_callback= => nil) - @searcher.stubs(:network).returns(@connection) # neuter the network connection + describe "#destroy" do + let(:http_method) { :delete } + let(:response) { mock_response(200, 'body') } + let(:connection) { stub('mock http connection', :delete => response, :verify_callback= => nil) } + let(:request) { delete_request('foo') } - @request = Puppet::Indirector::Request.new(:foo, :destroy, "foo bar") + before :each do + terminus.stubs(:network).returns(connection) end + it_behaves_like 'a REST terminus method', :destroy + it_behaves_like 'a deserializing terminus method', :destroy + it "should call the DELETE http method on a network connection" do - @searcher.expects(:network).returns @connection - @connection.expects(:delete).returns @response - @searcher.destroy(@request) + connection.expects(:delete).with('/production/test_model/foo', has_key('Accept')).returns(response) + + terminus.destroy(request) end it "should fail if any options are provided, since DELETE apparently does not support query options" do - @request.stubs(:options).returns(:one => "two", :three => "four") + request = delete_request('foo', :one => "two", :three => "four") - lambda { @searcher.destroy(@request) }.should raise_error(ArgumentError) + expect { terminus.destroy(request) }.to raise_error(ArgumentError) end it "should deserialize and return the http response" do - @connection.expects(:delete).returns @response - @searcher.expects(:deserialize).with(@response).returns "myobject" - - @searcher.destroy(@request).should == 'myobject' - end + connection.expects(:delete).returns response - it "should use the URI generated by the Handler module" do - @searcher.expects(:indirection2uri).with(@request).returns "/my/uri" - @connection.expects(:delete).with { |path, args| path == "/my/uri" }.returns(@response) - @searcher.destroy(@request) + terminus.destroy(request).should == model.new('', 'body') end - it "should not include the query string" do - @connection.stubs(:delete).returns @response - @searcher.destroy(@request) - end + it "returns nil on 404" do + response = mock_response('404', nil) - it "should provide an Accept header containing the list of supported formats joined with commas" do - @connection.expects(:delete).with { |path, args| args["Accept"] == "supported, formats" }.returns(@response) + connection.expects(:delete).returns(response) - @searcher.model.expects(:supported_formats).returns %w{supported formats} - @searcher.destroy(@request) + terminus.destroy(request).should == nil end - it "should deserialize and return the network response" do - @searcher.expects(:deserialize).with(@response).returns @instance - @searcher.destroy(@request).should equal(@instance) - end + it "should provide an Accept header containing the list of supported formats joined with commas" do + connection.expects(:delete).with(anything, has_entry("Accept" => "supported, formats")).returns(response) - it "should generate an error when result data deserializes fails" do - @searcher.expects(:deserialize).raises(ArgumentError) - lambda { @searcher.destroy(@request) }.should raise_error(ArgumentError) + terminus.model.expects(:supported_formats).returns %w{supported formats} + terminus.destroy(request) end end - describe "when doing a save" do - before :each do - @connection = stub('mock http connection', :put => @response, :verify_callback= => nil) - @searcher.stubs(:network).returns(@connection) # neuter the network connection + describe "#save" do + let(:http_method) { :put } + let(:response) { mock_response(200, 'body') } + let(:connection) { stub('mock http connection', :put => response, :verify_callback= => nil) } + let(:instance) { model.new('the thing', 'some contents') } + let(:request) { save_request(instance.name, instance) } - @instance = stub 'instance', :render => "mydata", :mime => "mime" - @request = Puppet::Indirector::Request.new(:foo, :save, "foo bar") - @request.instance = @instance + before :each do + terminus.stubs(:network).returns(connection) end - it "should call the PUT http method on a network connection" do - @searcher.expects(:network).returns @connection - @connection.expects(:put).returns @response - @searcher.save(@request) - end + it_behaves_like 'a REST terminus method', :save - it "should fail if any options are provided, since DELETE apparently does not support query options" do - @request.stubs(:options).returns(:one => "two", :three => "four") + it "should call the PUT http method on a network connection" do + connection.expects(:put).with('/production/test_model/the%20thing', anything, has_key("Content-Type")).returns response - lambda { @searcher.save(@request) }.should raise_error(ArgumentError) + terminus.save(request) end - it "should use the URI generated by the Handler module" do - @searcher.expects(:indirection2uri).with(@request).returns "/my/uri" - @connection.expects(:put).with { |path, args| path == "/my/uri" }.returns(@response) - @searcher.save(@request) + it "should fail if any options are provided, since PUT apparently does not support query options" do + request = save_request(instance, :one => "two", :three => "four") + + expect { terminus.save(request) }.to raise_error(ArgumentError) end it "should serialize the instance using the default format and pass the result as the body of the request" do - @instance.expects(:render).returns "serial_instance" - @connection.expects(:put).with { |path, data, args| data == "serial_instance" }.returns @response + instance.expects(:render).returns "serial_instance" + connection.expects(:put).with(anything, "serial_instance", anything).returns response - @searcher.save(@request) + terminus.save(request) end - it "should deserialize and return the http response" do - @connection.expects(:put).returns @response - @searcher.expects(:deserialize).with(@response).returns "myobject" + it "returns nil on 404" do + response = mock_response('404', nil) - @searcher.save(@request).should == 'myobject' + connection.expects(:put).returns(response) + + terminus.save(request).should == nil end - it "should provide an Accept header containing the list of supported formats joined with commas" do - @connection.expects(:put).with { |path, data, args| args["Accept"] == "supported, formats" }.returns(@response) + it "returns nil" do + connection.expects(:put).returns response - @searcher.model.expects(:supported_formats).returns %w{supported formats} - @searcher.save(@request) + terminus.save(request).should be_nil end - it "should provide a Content-Type header containing the mime-type of the sent object" do - @connection.expects(:put).with { |path, data, args| args['Content-Type'] == "mime" }.returns(@response) + it "should provide an Accept header containing the list of supported formats joined with commas" do + connection.expects(:put).with(anything, anything, has_entry("Accept" => "supported, formats")).returns(response) - @instance.expects(:mime).returns "mime" - @searcher.save(@request) - end + instance.expects(:render).returns('') + model.expects(:supported_formats).returns %w{supported formats} + instance.expects(:mime).returns "supported" - it "should deserialize and return the network response" do - @searcher.expects(:deserialize).with(@response).returns @instance - @searcher.save(@request).should equal(@instance) + terminus.save(request) end - it "should generate an error when result data deserializes fails" do - @searcher.expects(:deserialize).raises(ArgumentError) - lambda { @searcher.save(@request) }.should raise_error(ArgumentError) + it "should provide a Content-Type header containing the mime-type of the sent object" do + instance.expects(:mime).returns "mime" + connection.expects(:put).with(anything, anything, has_entry('Content-Type' => "mime")).returns(response) + + terminus.save(request) end end end diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb index c6b575e15..9afad9d76 100755 --- a/spec/unit/module_spec.rb +++ b/spec/unit/module_spec.rb @@ -604,7 +604,8 @@ describe Puppet::Module, "when finding matching manifests" do end it "should default to the 'init' file if no glob pattern is specified" do - Dir.expects(:glob).with("/a/manifests/init.{pp,rb}").returns(%w{/a/manifests/init.pp}) + FileTest.expects(:exist?).with("/a/manifests/init.pp").returns(true) + FileTest.expects(:exist?).with("/a/manifests/init.rb").returns(false) @mod.match_manifests(nil).should == %w{/a/manifests/init.pp} end @@ -626,6 +627,12 @@ describe Puppet::Module, "when finding matching manifests" do @mod.match_manifests(@pq_glob_with_extension).should == [] end + + it "should raise an error if the pattern tries to leave the manifest directory" do + expect do + @mod.match_manifests("something/../../*") + end.to raise_error(Puppet::Module::InvalidFilePattern, /The pattern "something\/\.\.\/\.\.\/\*" to find manifests in the module "mymod" is invalid and potentially unsafe./) + end end describe Puppet::Module do diff --git a/spec/unit/module_tool/applications/unpacker_spec.rb b/spec/unit/module_tool/applications/unpacker_spec.rb index 7db0b7d0a..f32928dea 100644 --- a/spec/unit/module_tool/applications/unpacker_spec.rb +++ b/spec/unit/module_tool/applications/unpacker_spec.rb @@ -36,6 +36,9 @@ describe Puppet::ModuleTool::Applications::Unpacker, :fails_on_windows => true d 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) + Puppet::Util.expects(:execute).with("find #{build_dir} -type d -exec chmod 755 {} +").returns(true) + Puppet::Util.expects(:execute).with("find #{build_dir} -type f -exec chmod 644 {} +").returns(true) + Puppet::Util.expects(:execute).with("chown -R #{build_dir.stat.uid}:#{build_dir.stat.gid} #{build_dir}").returns(true) unpacker.run end end @@ -48,6 +51,9 @@ describe Puppet::ModuleTool::Applications::Unpacker, :fails_on_windows => true d 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) + Puppet::Util.expects(:execute).with("find #{build_dir} -type d -exec chmod 755 {} +").returns(true) + Puppet::Util.expects(:execute).with("find #{build_dir} -type f -exec chmod 644 {} +").returns(true) + Puppet::Util.expects(:execute).with("chown -R #{build_dir.stat.uid}:#{build_dir.stat.gid} #{build_dir}").returns(true) unpacker.run end diff --git a/spec/unit/network/formats_spec.rb b/spec/unit/network/formats_spec.rb index 98c4df0c0..8db4bf7ab 100755 --- a/spec/unit/network/formats_spec.rb +++ b/spec/unit/network/formats_spec.rb @@ -55,16 +55,29 @@ describe "Puppet Network Format" do @yaml.render_multiple(instances).should == "foo" end - it "should safely load YAML when interning" do - text = "foo" - YAML.expects(:safely_load).with("foo").returns "bar" - @yaml.intern(String, text).should == "bar" + it "should deserialize YAML" do + @yaml.intern(String, YAML.dump("foo")).should == "foo" end - it "should safely load YAML when interning multiples" do - text = "foo" - YAML.expects(:safely_load).with("foo").returns "bar" - @yaml.intern_multiple(String, text).should == "bar" + it "should deserialize symbols as strings" do + @yaml.intern(String, YAML.dump(:foo)).should == "foo" + end + + it "should fail when type does not match deserialized form and has no from_pson" do + expect do + @yaml.intern(Hash, YAML.dump("foo")) + end.to raise_error(NoMethodError) + end + + it "should load from yaml when deserializing an array" do + text = YAML.dump(["foo"]) + @yaml.intern_multiple(String, text).should == ["foo"] + end + + it "should fail when one element does not have a from_pson" do + expect do + @yaml.intern_multiple(Hash, YAML.dump(["foo"])) + end.to raise_error(NoMethodError) end end @@ -108,29 +121,25 @@ describe "Puppet Network Format" do @yaml.render(instances).should == "bar" end - it "should intern by calling decode" do - text = "foo" - @yaml.expects(:decode).with("foo").returns "bar" - @yaml.intern(String, text).should == "bar" + it "should round trip data" do + @yaml.intern(String, @yaml.encode("foo")).should == "foo" end - it "should intern multiples by calling 'decode'" do - text = "foo" - @yaml.expects(:decode).with("foo").returns "bar" - @yaml.intern_multiple(String, text).should == "bar" + it "should round trip multiple data elements" do + data = @yaml.render_multiple(["foo", "bar"]) + @yaml.intern_multiple(String, data).should == ["foo", "bar"] end - it "should decode by base64 decoding, uncompressing and safely Yaml loading" do - Base64.expects(:decode64).with("zorg").returns "foo" - Zlib::Inflate.expects(:inflate).with("foo").returns "baz" - YAML.expects(:safely_load).with("baz").returns "bar" - @yaml.decode("zorg").should == "bar" + it "should intern by base64 decoding, uncompressing and safely Yaml loading" do + input = Base64.encode64(Zlib::Deflate.deflate(YAML.dump("data in"))) + + @yaml.intern(String, input).should == "data in" end - it "should encode by compressing and base64 encoding" do - Zlib::Deflate.expects(:deflate).with("foo", Zlib::BEST_COMPRESSION).returns "bar" - Base64.expects(:encode64).with("bar").returns "baz" - @yaml.encode("foo").should == "baz" + it "should render by compressing and base64 encoding" do + output = @yaml.render("foo") + + YAML.load(Zlib::Inflate.inflate(Base64.decode64(output))).should == "foo" end describe "when zlib is disabled" do @@ -143,11 +152,11 @@ describe "Puppet Network Format" do end it "should refuse to encode" do - lambda{ @yaml.encode("foo") }.should raise_error + expect { @yaml.render("foo") }.to raise_error(Puppet::Error, /zlib library is not installed/) end it "should refuse to decode" do - lambda{ @yaml.decode("foo") }.should raise_error + expect { @yaml.intern(String, "foo") }.to raise_error(Puppet::Error, /zlib library is not installed/) end end diff --git a/spec/unit/network/http/handler_spec.rb b/spec/unit/network/http/handler_spec.rb index 7d9b5ae0c..e0f91a6bf 100755 --- a/spec/unit/network/http/handler_spec.rb +++ b/spec/unit/network/http/handler_spec.rb @@ -133,21 +133,12 @@ describe Puppet::Network::HTTP::Handler do decoded_params.should == {:my_param => [1,2,3]} end - it "should accept YAML parameters with !ruby/hash tags on Ruby 1.8", :if => RUBY_VERSION =~ /^1\.8/ do - params = {'my_param' => "--- !ruby/hash:Array {}"} + it "should ignore tags on YAML parameters" do + params = {'my_param' => "--- !ruby/object:Array {}"} decoded_params = @handler.send(:decode_params, params) - decoded_params[:my_param].should be_an(Array) - end - - # These are only dangerous with Psych, which is Ruby 1.9-only. Since - # there's no real way to change the yamler in Puppet, assume that 1.9 means - # Psych, especially in tests. - it "should fail if YAML parameters have !ruby/hash tags on Ruby 1.9", :unless => RUBY_VERSION =~ /^1\.8/ do - params = {'my_param' => "--- !ruby/hash:Array {}"} - - expect { @handler.send(:decode_params, params) }.to raise_error(ArgumentError, /Illegal YAML mapping found/) + decoded_params[:my_param].should be_a(Hash) end describe "when finding a model instance" do diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 33bb4d1b2..ff2751643 100755 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -36,6 +36,87 @@ describe Puppet::Node do node.environment.name.should == :bar end end + + it "can survive a round-trip through YAML" do + facts = Puppet::Node::Facts.new("hello", "one" => "c", "two" => "b") + node = Puppet::Node.new("hello", + :environment => 'kjhgrg', + :classes => ['erth', 'aiu'], + :parameters => {"hostname"=>"food"} + ) + new_node = Puppet::Node.convert_from('yaml', node.render('yaml')) + new_node.environment.should == node.environment + new_node.parameters.should == node.parameters + new_node.classes.should == node.classes + new_node.name.should == node.name + end + + describe "when converting to json" do + before do + @node = Puppet::Node.new("mynode") + end + + it "should provide its name" do + @node.should set_json_attribute('name').to("mynode") + end + + it "should produce a hash with the document_type set to 'Node'" do + @node.should set_json_document_type_to("Node") + end + + it "should include the classes if set" do + @node.classes = %w{a b c} + @node.should set_json_attribute("classes").to(%w{a b c}) + end + + it "should not include the classes if there are none" do + @node.should_not set_json_attribute('classes') + end + + it "should include parameters if set" do + @node.parameters = {"a" => "b", "c" => "d"} + @node.should set_json_attribute('parameters').to({"a" => "b", "c" => "d"}) + end + + it "should not include the parameters if there are none" do + @node.should_not set_json_attribute('parameters') + end + + it "should include the environment" do + @node.environment = "production" + @node.should set_json_attribute('environment').to('production') + end + end + + describe "when converting from json" do + before do + @node = Puppet::Node.new("mynode") + @format = Puppet::Network::FormatHandler.format('pson') + end + + def from_json(json) + @format.intern(Puppet::Node, json) + end + + it "should set its name" do + Puppet::Node.should read_json_attribute('name').from(@node.to_pson).as("mynode") + end + + it "should include the classes if set" do + @node.classes = %w{a b c} + Puppet::Node.should read_json_attribute('classes').from(@node.to_pson).as(%w{a b c}) + end + + it "should include parameters if set" do + @node.parameters = {"a" => "b", "c" => "d"} + Puppet::Node.should read_json_attribute('parameters').from(@node.to_pson).as({"a" => "b", "c" => "d"}) + end + + it "should include the environment" do + @node.environment = "production" + Puppet::Node.should read_json_attribute('environment').from(@node.to_pson).as(Puppet::Node::Environment.new(:production)) + end + end end describe Puppet::Node, "when initializing" do diff --git a/spec/unit/parser/files_spec.rb b/spec/unit/parser/files_spec.rb index dc79984c8..b5ea1526f 100755 --- a/spec/unit/parser/files_spec.rb +++ b/spec/unit/parser/files_spec.rb @@ -10,14 +10,6 @@ describe Puppet::Parser::Files do @basepath = make_absolute("/somepath") end - it "should have a method for finding a template" do - Puppet::Parser::Files.should respond_to(:find_template) - end - - it "should have a method for finding manifests" do - Puppet::Parser::Files.should respond_to(:find_manifests) - end - describe "when searching for templates" do it "should return fully-qualified templates directly" do Puppet::Parser::Files.expects(:modulepath).never @@ -127,75 +119,22 @@ describe Puppet::Parser::Files do describe "when searching for manifests" do it "should ignore invalid modules" do mod = mock 'module' - Puppet::Node::Environment.new.expects(:module).with("mymod").raises(Puppet::Module::InvalidName, "name is invalid") + env = Puppet::Node::Environment.new + env.expects(:module).with("mymod").raises(Puppet::Module::InvalidName, "name is invalid") Puppet.expects(:value).with(:modulepath).never Dir.stubs(:glob).returns %w{foo} - Puppet::Parser::Files.find_manifests("mymod/init.pp") - end - end - - describe "when searching for manifests when no module is found" do - before do - File.stubs(:find).returns(nil) - end - - it "should not look for modules when paths are fully qualified" do - Puppet.expects(:value).with(:modulepath).never - file = @basepath + "/fully/qualified/file.pp" - Dir.stubs(:glob).with(file).returns([file]) - Puppet::Parser::Files.find_manifests(file) - end - - it "should return nil and an array of fully qualified files" do - file = @basepath + "/fully/qualified/file.pp" - Dir.stubs(:glob).with(file).returns([file]) - Puppet::Parser::Files.find_manifests(file).should == [nil, [file]] - end - - it "should match against provided fully qualified patterns" do - pattern = @basepath + "/fully/qualified/pattern/*" - Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns(%w{my file list}) - Puppet::Parser::Files.find_manifests(pattern)[1].should == %w{my file list} - end - - it "should look for files relative to the current directory" do - # We expand_path to normalize backslashes and slashes on Windows - cwd = File.expand_path(Dir.getwd) - Dir.expects(:glob).with("#{cwd}/foobar/init.pp").returns(["#{cwd}/foobar/init.pp"]) - Puppet::Parser::Files.find_manifests("foobar/init.pp")[1].should == ["#{cwd}/foobar/init.pp"] - end - - it "should only return files, not directories" do - pattern = @basepath + "/fully/qualified/pattern/*" - file = @basepath + "/my/file" - dir = @basepath + "/my/directory" - Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns([file, dir]) - FileTest.expects(:directory?).with(file).returns(false) - FileTest.expects(:directory?).with(dir).returns(true) - Puppet::Parser::Files.find_manifests(pattern)[1].should == [file] - end - - it "should return files once only" do - pattern = @basepath + "/fully/qualified/pattern/*" - Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns(%w{one two one}) - Puppet::Parser::Files.find_manifests(pattern)[1].should == %w{one two} + Puppet::Parser::Files.find_manifests_in_modules("mymod/init.pp", env) end end describe "when searching for manifests in a found module" do it "should return the name of the module and the manifests from the first found module" do mod = Puppet::Module.new("mymod") - Puppet::Node::Environment.new.expects(:module).with("mymod").returns mod - mod.expects(:match_manifests).with("init.pp").returns(%w{/one/mymod/manifests/init.pp}) - Puppet::Parser::Files.find_manifests("mymod/init.pp").should == ["mymod", ["/one/mymod/manifests/init.pp"]] - end - - it "should use the node environment if specified" do - mod = Puppet::Module.new("mymod") - Puppet::Node::Environment.new("myenv").expects(:module).with("mymod").returns mod + env = Puppet::Node::Environment.new + env.expects(:module).with("mymod").returns mod mod.expects(:match_manifests).with("init.pp").returns(%w{/one/mymod/manifests/init.pp}) - Puppet::Parser::Files.find_manifests("mymod/init.pp", :environment => "myenv")[1].should == ["/one/mymod/manifests/init.pp"] + Puppet::Parser::Files.find_manifests_in_modules("mymod/init.pp", env).should == ["mymod", ["/one/mymod/manifests/init.pp"]] end after { Puppet.settings.clear } diff --git a/spec/unit/parser/parser_spec.rb b/spec/unit/parser/parser_spec.rb index beb046845..28a8223f5 100755 --- a/spec/unit/parser/parser_spec.rb +++ b/spec/unit/parser/parser_spec.rb @@ -32,11 +32,21 @@ describe Puppet::Parser do parser.known_resource_types.should equal(rtc) end - it "should delegate importing to the known resource type loader" do - parser = Puppet::Parser::Parser.new "development" - parser.known_resource_types.loader.expects(:import).with("newfile", "current_file") - parser.lexer.expects(:file).returns "current_file" - parser.import("newfile") + context "when importing" do + it "uses the directory of the currently parsed file" do + @parser.lexer.stubs(:file).returns "/tmp/current_file" + + @parser.known_resource_types.loader.expects(:import).with("newfile", "/tmp") + + @parser.import("newfile") + end + + it "uses the current working directory, when there is no file being parsed" do + @parser.known_resource_types.loader.expects(:import).with('one', Dir.pwd) + @parser.known_resource_types.loader.expects(:import).with('two', Dir.pwd) + + @parser.parse("import 'one', 'two'") + end end describe "when parsing files" do diff --git a/spec/unit/parser/type_loader_spec.rb b/spec/unit/parser/type_loader_spec.rb index 8b139613a..ff22f54b0 100755 --- a/spec/unit/parser/type_loader_spec.rb +++ b/spec/unit/parser/type_loader_spec.rb @@ -31,8 +31,8 @@ describe Puppet::Parser::TypeLoader do end it "should attempt to import each generated name" do - @loader.expects(:import).with("foo/bar",nil).returns([]) - @loader.expects(:import).with("foo",nil).returns([]) + @loader.expects(:import_from_modules).with("foo/bar", anything).returns([]) + @loader.expects(:import_from_modules).with("foo", anything).returns([]) @loader.try_load_fqname(:hostclass, "foo::bar") { |f| false } end end @@ -45,50 +45,30 @@ describe Puppet::Parser::TypeLoader do end it "should return immediately when imports are being ignored" do - Puppet::Parser::Files.expects(:find_manifests).never + Puppet::Parser::Files.expects(:find_manifests_in_modules).never Puppet[:ignoreimport] = true - @loader.import("foo").should be_nil + @loader.import("foo", "/path").should be_nil end it "should find all manifests matching the file or pattern" do - Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| pat == "myfile" }.returns ["modname", %w{one}] - @loader.import("myfile") - end - - it "should use the directory of the current file if one is set" do - Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == make_absolute("/current") }.returns ["modname", %w{one}] - @loader.import("myfile", make_absolute("/current/file")) + Puppet::Parser::Files.expects(:find_manifests_in_modules).with("myfile", anything).returns ["modname", %w{one}] + @loader.import("myfile", "/path") end it "should pass the environment when looking for files" do - Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:environment] == @loader.environment }.returns ["modname", %w{one}] - @loader.import("myfile") + Puppet::Parser::Files.expects(:find_manifests_in_modules).with(anything, @loader.environment).returns ["modname", %w{one}] + @loader.import("myfile", "/path") end it "should fail if no files are found" do - Puppet::Parser::Files.expects(:find_manifests).returns [nil, []] - lambda { @loader.import("myfile") }.should raise_error(Puppet::ImportError) + Puppet::Parser::Files.expects(:find_manifests_in_modules).returns [nil, []] + lambda { @loader.import("myfile", "/path") }.should raise_error(Puppet::ImportError) end it "should parse each found file" do - Puppet::Parser::Files.expects(:find_manifests).returns ["modname", [make_absolute("/one")]] + Puppet::Parser::Files.expects(:find_manifests_in_modules).returns ["modname", [make_absolute("/one")]] @loader.expects(:parse_file).with(make_absolute("/one")).returns(Puppet::Parser::AST::Hostclass.new('')) - @loader.import("myfile") - end - - it "should make each file qualified before attempting to parse it" do - Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{one}] - @loader.expects(:parse_file).with(make_absolute("/current/one")).returns(Puppet::Parser::AST::Hostclass.new('')) - @loader.import("myfile", make_absolute("/current/file")) - end - - it "should not attempt to import files that have already been imported" do - Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{/one}] - Puppet::Parser::Parser.any_instance.expects(:parse).once.returns(Puppet::Parser::AST::Hostclass.new('')) - @loader.import("myfile") - - # This will fail if it tries to reimport the file. - @loader.import("myfile") + @loader.import("myfile", "/path") end end @@ -209,10 +189,11 @@ describe Puppet::Parser::TypeLoader do end end + it "should be able to add classes to the current resource type collection" do file = tmpfile("simple_file.pp") File.open(file, "w") { |f| f.puts "class foo {}" } - @loader.import(file) + @loader.import(File.basename(file), File.dirname(file)) @loader.known_resource_types.hostclass("foo").should be_instance_of(Puppet::Resource::Type) end diff --git a/spec/unit/resource/type_collection_spec.rb b/spec/unit/resource/type_collection_spec.rb index 0c997c2ad..13f9fa35f 100755 --- a/spec/unit/resource/type_collection_spec.rb +++ b/spec/unit/resource/type_collection_spec.rb @@ -55,6 +55,14 @@ describe Puppet::Resource::TypeCollection do @code.node("foo").should equal(node) end + it "should fail if a duplicate node is added" do + @code.add(Puppet::Resource::Type.new(:node, "foo")) + + expect do + @code.add(Puppet::Resource::Type.new(:node, "foo")) + end.to raise_error(Puppet::ParseError, /cannot redefine/) + end + it "should store hostclasses as hostclasses" do klass = Puppet::Resource::Type.new(:hostclass, "foo") @@ -62,6 +70,16 @@ describe Puppet::Resource::TypeCollection do @code.hostclass("foo").should equal(klass) end + it "merge together hostclasses of the same name" do + klass1 = Puppet::Resource::Type.new(:hostclass, "foo", :doc => "first") + klass2 = Puppet::Resource::Type.new(:hostclass, "foo", :doc => "second") + + @code.add(klass1) + @code.add(klass2) + + @code.hostclass("foo").doc.should == "firstsecond" + end + it "should store definitions as definitions" do define = Puppet::Resource::Type.new(:definition, "foo") @@ -69,13 +87,12 @@ describe Puppet::Resource::TypeCollection do @code.definition("foo").should equal(define) end - it "should merge new classes with existing classes of the same name" do - loader = Puppet::Resource::TypeCollection.new("env") - first = Puppet::Resource::Type.new(:hostclass, "foo") - second = Puppet::Resource::Type.new(:hostclass, "foo") - loader.add first - first.expects(:merge).with(second) - loader.add(second) + it "should fail if a duplicate definition is added" do + @code.add(Puppet::Resource::Type.new(:definition, "foo")) + + expect do + @code.add(Puppet::Resource::Type.new(:definition, "foo")) + end.to raise_error(Puppet::ParseError, /cannot be redefined/) end it "should remove all nodes, classes, and definitions when cleared" do @@ -170,58 +187,27 @@ describe Puppet::Resource::TypeCollection do end %w{hostclass node definition}.each do |data| - before do - @instance = Puppet::Resource::Type.new(data, "foo") - end - - it "should have a method for adding a #{data}" do - Puppet::Resource::TypeCollection.new("env").should respond_to("add_#{data}") - end + describe "behavior of add for #{data}" do - it "should use the name of the instance to add it" do - loader = Puppet::Resource::TypeCollection.new("env") - loader.send("add_#{data}", @instance) - loader.send(data, @instance.name).should equal(@instance) - end - - unless data == "hostclass" - it "should fail to add a #{data} when one already exists" do + it "should return the added #{data}" do loader = Puppet::Resource::TypeCollection.new("env") - loader.add @instance - lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError) - end - end + instance = Puppet::Resource::Type.new(data, "foo") - it "should return the added #{data}" do - loader = Puppet::Resource::TypeCollection.new("env") - - loader.add(@instance).should equal(@instance) - end + loader.add(instance).should equal(instance) + end - it "should be able to retrieve #{data} by name" do - loader = Puppet::Resource::TypeCollection.new("env") - instance = Puppet::Resource::Type.new(data, "bar") - loader.add instance - loader.send(data, "bar").should equal(instance) - end + it "should retrieve #{data} insensitive to case" do + loader = Puppet::Resource::TypeCollection.new("env") + instance = Puppet::Resource::Type.new(data, "Bar") - it "should retrieve #{data} insensitive to case" do - loader = Puppet::Resource::TypeCollection.new("env") - instance = Puppet::Resource::Type.new(data, "Bar") - loader.add instance - loader.send(data, "bAr").should equal(instance) - end + loader.add instance - it "should return nil when asked for a #{data} that has not been added" do - Puppet::Resource::TypeCollection.new("env").send(data, "foo").should be_nil - end + loader.send(data, "bAr").should equal(instance) + end - it "should be able to retrieve all #{data}s" do - plurals = { "hostclass" => "hostclasses", "node" => "nodes", "definition" => "definitions" } - loader = Puppet::Resource::TypeCollection.new("env") - instance = Puppet::Resource::Type.new(data, "foo") - loader.add instance - loader.send(plurals[data]).should == { "foo" => instance } + it "should return nil when asked for a #{data} that has not been added" do + Puppet::Resource::TypeCollection.new("env").send(data, "foo").should be_nil + end end end @@ -311,7 +297,7 @@ describe Puppet::Resource::TypeCollection do end end - + it "should not look in the local scope for classes when the name is qualified" do @loader = Puppet::Resource::TypeCollection.new("env") @loader.add Puppet::Resource::Type.new(:hostclass, "foo::bar") @@ -445,7 +431,5 @@ describe Puppet::Resource::TypeCollection do lambda { @code.version }.should raise_error(Puppet::ParseError) end - end - end diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index ea07443d7..48f4c2608 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -444,41 +444,11 @@ describe Puppet::Resource do @resource["two"] = "other" end - it "should be able to be dumped to yaml" do - expect { YAML.dump(@resource) }.to_not raise_error - end - it "should produce an equivalent yaml object" do - text = YAML.dump(@resource) - - newresource = YAML.load(text) - newresource.title.should == @resource.title - newresource.type.should == @resource.type - %w{one two}.each do |param| - newresource[param].should == @resource[param] - end - end - end - - describe "when loading 0.25.x storedconfigs YAML" do - before :each do - @old_storedconfig_yaml = %q{--- !ruby/object:Puppet::Resource::Reference -builtin_type: -title: /tmp/bar -type: File -} - end - - it "should deserialize a Puppet::Resource::Reference without exceptions" do - expect { YAML.load(@old_storedconfig_yaml) }.to_not raise_error - end - - it "should deserialize as a Puppet::Resource::Reference as a Puppet::Resource" do - YAML.load(@old_storedconfig_yaml).class.should == Puppet::Resource - end + text = @resource.render('yaml') - it "should to_hash properly" do - YAML.load(@old_storedconfig_yaml).to_hash.should == { :path => "/tmp/bar" } + newresource = Puppet::Resource.convert_from('yaml', text) + newresource.should equal_attributes_of @resource end end @@ -653,13 +623,13 @@ type: File resource = Puppet::Resource.new("File", "/foo") resource.exported = true - Puppet::Resource.from_pson(PSON.parse(resource.to_pson)).exported.should be_true + Puppet::Resource.from_pson(PSON.parse(resource.to_pson)).exported?.should be_true end it "should set 'exported' to false if no value is set" do resource = Puppet::Resource.new("File", "/foo") - Puppet::Resource.from_pson(PSON.parse(resource.to_pson)).exported.should be_false + Puppet::Resource.from_pson(PSON.parse(resource.to_pson)).exported?.should be_false end it "should set all of its parameters as the 'parameters' entry" do diff --git a/spec/unit/run_spec.rb b/spec/unit/run_spec.rb index ea6ec74b1..ceea61c66 100755 --- a/spec/unit/run_spec.rb +++ b/spec/unit/run_spec.rb @@ -116,21 +116,35 @@ describe Puppet::Run do end describe ".from_pson" do - it "should accept a hash of options, and pass them with symbolified keys to new" do + it "should read from a hash that represents the 'options' to initialize" do options = { "tags" => "whatever", "background" => true, + "ignoreschedules" => false, } + run = Puppet::Run.from_pson(options) - - Puppet::Run.expects(:new).with( - { + run.options.should == { :tags => "whatever", - :background => true, - - }) + :ignoreschedules => false, + } + run.background.should be_true + end - Puppet::Run.from_pson(options) + it "should read from a hash that follows the actual object structure" do + hash = {"background" => true, + "options" => { + "tags" => [], + "ignoreschedules" => false}, + "status" => "success"} + run = Puppet::Run.from_pson(hash) + + run.options.should == { + :tags => [], + :ignoreschedules => false + } + run.background.should be_true + run.status.should == 'success' end end end diff --git a/spec/unit/status_spec.rb b/spec/unit/status_spec.rb index 0c572fd95..d3cd5cfc2 100755 --- a/spec/unit/status_spec.rb +++ b/spec/unit/status_spec.rb @@ -31,4 +31,10 @@ describe Puppet::Status do it "should allow a name to be set" do Puppet::Status.new.name = "status" end + + it "can do a round-trip serialization via YAML" do + status = Puppet::Status.new + new_status = Puppet::Status.convert_from('yaml', status.render('yaml')) + new_status.should equal_attributes_of(status) + end end diff --git a/test/network/handler/report.rb b/test/network/handler/report.rb index d0c223878..58f29cdc1 100755 --- a/test/network/handler/report.rb +++ b/test/network/handler/report.rb @@ -31,42 +31,6 @@ class TestReportServer < Test::Unit::TestCase client end - def test_process - server = Puppet::Network::Handler.report.new - - # We have to run multiple reports to make sure there's no conflict - reports = [] - $run = [] - 2.times do |i| - name = "processtest#{i}" - reports << name - - Report.newreport(name) do - def process - $run << self.report_name - end - end - end - Puppet[:reports] = reports.collect { |r| r.to_s }.join(",") - - report = fakereport - - retval = nil - assert_nothing_raised { - retval = server.send(:process, YAML.dump(report)) - } - - reports.each do |name| - assert($run.include?(name.intern), "Did not run #{name}") - end - - # Now make sure our server doesn't die on missing reports - Puppet[:reports] = "fakereport" - assert_nothing_raised { - retval = server.send(:process, YAML.dump(report)) - } - end - def test_reports Puppet[:reports] = "myreport" |
