summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG285
-rw-r--r--Rakefile3
-rwxr-xr-xconf/osx/createpackage.sh12
-rwxr-xr-xconf/osx/preflight4
-rw-r--r--conf/redhat/client.init7
-rw-r--r--conf/redhat/server.init6
-rwxr-xr-xext/puppetlast3
-rw-r--r--ext/rack/README4
-rw-r--r--ext/regexp_nodes/classes/databases2
-rw-r--r--ext/regexp_nodes/classes/webservers2
-rw-r--r--ext/regexp_nodes/parameters/environment/prod1
-rw-r--r--ext/regexp_nodes/parameters/environment/qa3
-rw-r--r--ext/regexp_nodes/regexp_nodes.rb215
-rw-r--r--lib/puppet/agent.rb4
-rw-r--r--lib/puppet/application/puppetd.rb9
-rw-r--r--lib/puppet/application/puppetdoc.rb7
-rw-r--r--lib/puppet/configurer.rb10
-rw-r--r--lib/puppet/configurer/fact_handler.rb9
-rw-r--r--lib/puppet/defaults.rb12
-rw-r--r--lib/puppet/external/pson/common.rb2
-rw-r--r--lib/puppet/external/pson/pure.rb4
-rw-r--r--lib/puppet/file_serving/base.rb17
-rw-r--r--lib/puppet/file_serving/configuration.rb4
-rw-r--r--lib/puppet/file_serving/metadata.rb45
-rw-r--r--lib/puppet/indirector/catalog/active_record.rb5
-rw-r--r--lib/puppet/indirector/facts/facter.rb2
-rw-r--r--lib/puppet/indirector/ldap.rb2
-rw-r--r--lib/puppet/indirector/node/ldap.rb2
-rwxr-xr-xlib/puppet/network/authstore.rb5
-rw-r--r--lib/puppet/network/format_handler.rb2
-rw-r--r--lib/puppet/network/formats.rb50
-rw-r--r--lib/puppet/network/http/rack/httphandler.rb18
-rw-r--r--lib/puppet/network/http/rack/rest.rb8
-rw-r--r--lib/puppet/network/http/rack/xmlrpc.rb8
-rw-r--r--lib/puppet/network/http_server/webrick.rb5
-rw-r--r--lib/puppet/node/environment.rb29
-rw-r--r--lib/puppet/parameter.rb18
-rw-r--r--lib/puppet/parser/ast/boolean_operator.rb4
-rw-r--r--lib/puppet/parser/collector.rb22
-rw-r--r--lib/puppet/parser/functions/generate.rb4
-rw-r--r--lib/puppet/parser/functions/require.rb5
-rw-r--r--lib/puppet/parser/functions/versioncmp.rb2
-rw-r--r--lib/puppet/parser/resource.rb6
-rwxr-xr-xlib/puppet/provider/package/dpkg.rb2
-rw-r--r--lib/puppet/provider/package/portage.rb50
-rw-r--r--lib/puppet/provider/package/rug.rb2
-rw-r--r--lib/puppet/provider/package/up2date.rb2
-rw-r--r--lib/puppet/provider/package/urpmi.rb2
-rw-r--r--lib/puppet/provider/service/daemontools.rb2
-rwxr-xr-xlib/puppet/provider/service/debian.rb2
-rw-r--r--lib/puppet/provider/service/runit.rb2
-rw-r--r--lib/puppet/provider/ssh_authorized_key/parsed.rb3
-rw-r--r--lib/puppet/provider/zone/solaris.rb17
-rw-r--r--lib/puppet/rails.rb4
-rw-r--r--lib/puppet/rails/resource.rb2
-rw-r--r--lib/puppet/resource/catalog.rb6
-rw-r--r--lib/puppet/resource/reference.rb34
-rw-r--r--lib/puppet/ssl/certificate_revocation_list.rb2
-rw-r--r--lib/puppet/ssl/host.rb5
-rw-r--r--lib/puppet/sslcertificates/ca.rb9
-rw-r--r--lib/puppet/transaction.rb27
-rw-r--r--lib/puppet/type.rb17
-rwxr-xr-xlib/puppet/type/cron.rb2
-rw-r--r--lib/puppet/type/file.rb52
-rwxr-xr-xlib/puppet/type/file/content.rb10
-rwxr-xr-xlib/puppet/type/file/mode.rb19
-rwxr-xr-xlib/puppet/type/file/owner.rb11
-rw-r--r--lib/puppet/type/k5login.rb2
-rwxr-xr-xlib/puppet/type/maillist.rb11
-rw-r--r--lib/puppet/type/resources.rb24
-rwxr-xr-xlib/puppet/type/tidy.rb11
-rw-r--r--lib/puppet/util.rb5
-rw-r--r--lib/puppet/util/log.rb4
-rw-r--r--lib/puppet/util/methodhelper.rb7
-rw-r--r--lib/puppet/util/monkey_patches.rb8
-rw-r--r--lib/puppet/util/rdoc/parser.rb17
-rw-r--r--lib/puppet/util/selinux.rb23
-rw-r--r--lib/puppet/util/subclass_loader.rb2
-rw-r--r--lib/puppet/util/suidmanager.rb12
-rw-r--r--lib/puppet/util/tagging.rb26
-rwxr-xr-xspec/integration/defaults.rb11
-rwxr-xr-xspec/integration/type/file.rb21
-rwxr-xr-xspec/unit/application/puppetd.rb2
-rwxr-xr-xspec/unit/application/puppetdoc.rb17
-rwxr-xr-xspec/unit/configurer.rb6
-rwxr-xr-xspec/unit/configurer/fact_handler.rb6
-rwxr-xr-xspec/unit/file_serving/configuration.rb18
-rwxr-xr-xspec/unit/file_serving/metadata.rb78
-rwxr-xr-xspec/unit/indirector/catalog/active_record.rb21
-rw-r--r--spec/unit/network/authstore.rb30
-rwxr-xr-xspec/unit/network/format_handler.rb36
-rwxr-xr-xspec/unit/network/formats.rb85
-rwxr-xr-xspec/unit/network/http/webrick.rb4
-rwxr-xr-xspec/unit/network/rights.rb2
-rwxr-xr-xspec/unit/node/environment.rb60
-rwxr-xr-xspec/unit/parser/collector.rb29
-rwxr-xr-xspec/unit/parser/functions/require.rb6
-rwxr-xr-xspec/unit/parser/resource.rb15
-rwxr-xr-xspec/unit/parser/resource/reference.rb7
-rwxr-xr-xspec/unit/parser/scope.rb2
-rwxr-xr-xspec/unit/property.rb6
-rwxr-xr-xspec/unit/provider/package/dpkg.rb7
-rwxr-xr-xspec/unit/provider/service/debian.rb2
-rwxr-xr-xspec/unit/provider/ssh_authorized_key/parsed.rb6
-rwxr-xr-xspec/unit/rails.rb11
-rwxr-xr-xspec/unit/ssl/certificate_revocation_list.rb12
-rwxr-xr-xspec/unit/transaction.rb43
-rwxr-xr-xspec/unit/type/cron.rb33
-rwxr-xr-xspec/unit/type/file/content.rb29
-rwxr-xr-xspec/unit/type/file/owner.rb14
-rwxr-xr-xspec/unit/type/maillist.rb42
-rw-r--r--spec/unit/type/resources.rb67
-rwxr-xr-xspec/unit/type/tidy.rb15
-rwxr-xr-xspec/unit/util/log.rb36
-rw-r--r--spec/unit/util/monkey_patches.rb103
-rwxr-xr-xspec/unit/util/selinux.rb42
-rwxr-xr-xspec/unit/util/tagging.rb10
-rw-r--r--tasks/rake/git_workflow.rake121
-rw-r--r--tasks/rake/mail_patches.rake35
-rw-r--r--tasks/rake/sign.rake14
-rw-r--r--test/data/providers/ssh_authorized_key/parsed/authorized_keys1
121 files changed, 2013 insertions, 395 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 171f499f5..24d68b9fc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,80 @@
-0.25.0
+0.25.1
======
+20e5222 Fixing #2689 - file owner warnings are reduced
+09fb3f7 Fixing #2752 - "require" loads "include"
+6846c32 Fixing some recently broken Scope tests
+0043392 Fixed typo in lib/puppet/indirector/ldap.rb
+6b254eb Fix #2753 - Do not "global allow" plugins/modules mount if some rules have been parsed
+ff3a7bc Re-fixed #2750 - Stop disabling the CRL or checking for a disabled CRL
+594c774 Revised partial fix for #2661 and related issues
+73d04c6 Bug #2534 Raise error if property appears twice
+7517572 Bug #1908 cron environment should allow empty vals
+febe707 Bug #1742 Invalid params to --color outputs 'nil'
+d383ab8 Use notice() in the versioncmp() docs
+9dff716 conf/redhat/*.init: Use -p option to killproc
+f47a70f Ticket #2665: Regexp exception on ++ in package names
+b6e4ef3 Fixed #2750 - Set :cacrl to nil instead of 'false' in puppetd
+2b57e06 Fix #2691 - Collection AR request should not include params if querying with tags
+e8bce7a Workaround #2668 - Compress facts so that the request size limit triggers less often
+e2ce790 Fixed #2737 - The zone provider needs to get acquainted with OpenSolaris
+aea1e5f Update Red Hat spec file for 0.25.1
+fbdded7 Ticket #2685 (Type error in ssh_authorized_keys)
+4d9f76a Fix for #2745 fakedata tests not working
+b4bcfe9 Fix for #2736, target doesn't work for ssh_authorized_keys
+ae528f6 Ticket #2734 PSON/JSON not serializing classes of a catalog
+f59f805 Bug #1900 Parsing of quoted $ in stdin
+6ba122f Fixing #2735 - node classes are immed. added to classlist
+bca3b70 Bundling of pure ruby json lib as "pson"
+ce46be5 Proposed alternative solution for #2664 (REGEX / DIV lexing)
+b0518c3 Fix for #2681 (duplicate resource)
+8a73082 Fix #2707 config_version fails more helpfully
+54ded1b Fixes #1719, this avoids calling the external binary *which* everytime we are looking for a binary
+4c3c279 Updated required Facter version in README
+fcce46a Fixed #2702 - Set :outputdir to "doc" if not specified
+3940dfb Fixed #2674 - createpackage.sh: problem finding install.rb
+3b548f4 Fix #2699 - Use --masterport for PUPPET_PORT variable
+a75bf50 This updates the portage provider in three ways:
+ad86e9e Fixes #2688. Macauthorization provider now handles booleans internally correctly.
+d891f7a Ticket #2676 (a typo)
+bfba2cd Fix #2672 - Make sure nodenames keep their underscores when used as classname
+db67e5f Added rcov exclusion to Rakefile
+6912a7e Incremented version to 0.25.1
+fd322da Fixes #1538 - Fixes the yumrepo backtrace in noop mode.
+6551e86 Fix #2664 - Mathematic expressions mis-lexed as Regex
+a595033 Fix for #2654 (error generating error message)
+a951163 Fix #2642 - Runit provider rework
+96b5087 Fix for ticket #2639 (Puppet[:user]/Puppet[:group] vs. 'service')
+af57483 Fixing #2632 - 'require' works for 0.25 clients
+d42bda1 Fixing relationship metaparam backward compatibility
+d53bc16 Adding version information to the catalog for compat
+5f25589 Ticket #2626 (unhelpfull error messages)
+a1d3b04 Fixing #2617 - use the cert name as specified
+8987509 Refactored Puppet packaging and gem creation
+5c2ba47 FIXES 2616: Remove sync.syncronize and Puppet.info
+a53a77c Renamed test branch to testing in rake task
+d054fd9 Fixing #2656 - puppet parseonly tests don't hang
+cde70cf Fixes #2648. Spurious macauthorization parameter changes
+dcf0d0d Fix #2652 - Fix SELinux syntax error
+ba269f2 Fixed #2651 - Corrected install permissions on man page directories.
+361c502 Fix #2638 - Allow creating several nodes with matching names
+2283605 Added automatically constructed test branch task and file
+fd2a190 Fix for #2621 (JSON serialization of exec)
+577a45b Fix #2622 - Puppetdoc in single manifest to console is broken
+d2d7070 Fix #2640 - Daemontools and Runit were not creating the enable symlink
+d21b266 Fix #2627 - regex node name could lead to invalid tag
+cb90528 Merged fix for #2601
+b1554a1 Updated changelog task and CHANGELOG to version aware
+f5a106d Fix for #2637 (Webrick accpting connections on dead sockets)
+19e98f9 Fixed #2608 - install.rb will not run on ruby 1.9.1 due to ftools being deprecated
+40cd6d4 Fix for #2605 by falling back to alternative solution to #1963
+630407d Make regsubst() function operate on arrays (feature #2491).
+a45c435 Fix for #2600 (wrong number of arguments under older mongrel)
+f2bc8aa Fixed #2634 - Added servicegroup_name parameter to serviceescalation type
+7404e31 Fixs #2620 authconf interpolation, #2570 0-9 in domain names
+4344339 Fix for ticket #2618 (stubbing so redhat tests run under debian)
+c2e26b9 vim: match regexp language features
+1494bd7 Require active_record/version to support ActiveRecord < 2.3
+a5c56fc Fixed #2607 - Added Facter dependency for Puppet Gem
b1eddbb Updated and created new CHANGELOG format
994d6e0 Adding tests for the #2599 fix
42ab73f Ticket #2525 don't fail find_manifest on invalid module names
@@ -73,9 +148,6 @@ b611c34 Updated fix for #2481
f385072 Revert "Fxied #2481 - Added status and restart overrides for Red Hat service provider."
cc379b6 Fixed #2498 - logcheck update
85a3633 Removed extraneous debugging
-
-0.25.0rc1
-=========
bf94de9 Updated two more tests
5b87dba Logs now assume resource params have metadata
1410bed Adding metadata delegation from param to resource
@@ -338,6 +410,211 @@ f945b66 Fixing #2265 - rack is loaded with features rather than manually
5cc4910 Fix #1409 once again, including test
a6af5bf Added split function
+0.25.0
+======
+b1eddbb Updated and created new CHANGELOG format
+994d6e0 Adding tests for the #2599 fix
+42ab73f Ticket #2525 don't fail find_manifest on invalid module names
+a0f0dcc Updated permissions on test files
+d45812b Refactoring tests to reduce code size, increase coverage, and make
+aba2f66 This further normalizes the handling of init-style services (including
+fb236a0 Combined fix for #2525, #2552 -- RedHat service issues
+d40b942 Fixed #2589 - Renamed zfs delete to destroy and added tests
+4aa7fce Monkey patch to improve yaml compatibility between ruby versions
+1f6c74d Fixed typo in parser test
+2e9b706 Updated Red Hat spec file and RH patches for 0.25.0.
+19815dd Fixing #2592 - you can escape slashes in regexes
+ea58478 Fixing #2590 - modulepath is not cached inappropriately
+1a3d0c8 Fixed #2593: puppet init script status command not returning proper exit code
+8dabc72 Update documentation string to reflect actual intent of Puppet::Node::Facts::Rest
+b30a3c7 Fixes #2581. Use new 10.6 global launchd overrides file for service status/enabled
+7f05469 Fixed Naginator link
+e589cd3 Fixing #2582 - / no longer autorequires /
+3342b73 Fixing #2577 - clarifying and demoting the deprecation notice
+d397f8d Fixing #2574 - autoloading finds plugins in modules
+800a78b The first regex node now matches first
+6750aeb Fixing #2563 - multiple regex nodes now work together
+b728b93 Fixes #724 - false is equivalent to 'ruby -W1'
+a9d5863 Fix parser error output
+ee4f6ba Fixing #2551 - fixing content changed logs
+c8f859e Fix for test isolation portion of Ticket #2511
+6fa9271 Fixing #2549 - autoloading of top-level classes works again
+c752680 Fixing a heisenbug resulting from a race condition
+ea417d6 Fixing #2460 - puppetmasterd can now read the cert and key
+a49915a Not using the service user in settings when it's unavailable
+14ec838 Explicitly loading all facts in the directory service provider
+5ee6602 Adding an 'exists?' delegator from user type to provider
+06fcece Switching the owner/group settings to use symbolic values
+4eb325a Fixing the yamldir group to be a group instead of user
+058514a Moving Setting classes into separate files
+b0f219a Removing chuser on darwin restriction
+7f749cb Fixing a ruby warning in the authstore test
+c0da3bf Fixing #2558 - propagating recent fileserving changes
+ff39bc7 Fixes #2550 Handles case where metadata is nil
+47dee83 Ticket 2559 -- parseonly ignored specified file
+a4f6896 Fixed #2562 - Recognize the usecacheonfailure option again
+e408d6c Refactoring the Module/Environment co-interface
+796ba5c Fixing #1544 - plugins in modules now works again
+6bd3627 Adding a global cleanup to the spec_helper
+0ef5f22 Removed misguided case sensitivity tests
+c1967bb Fixes #2513. debian service provider now uses invoke-rc.d to determine enabled? status
+7e09247 Fixing fact-missing problem when puppet.conf is reparsed
+a35e9bf Fix for #2531; adds tests to confirm problem and related cases,
+299eadb Fixed #2530 - Fixed status setting in the SMF provider
+e6a7e82 Fixed spec typo
+75c6e4a Fixes #2493
+b62d966 conf/redhat/*.init: Fix condrestart/try-restart
+e9fbd4c conf/redhat/client.init: Fix #2123, status options on older RHEL
+0461a02 Updates to Solaris smf files to reflect new binary locations
+55a9cdb Fix #2517 - Stack overflow when CA cert missing
+601a2e5 Fix #2516 - Fix format detection when content-type contains charset
+d86bc88 Fix #2507 - Add missing integration tests
+aad3b76 Fix #2507 - Exported resources were not correctly collected.
+63cb1ad Fixes #2503
+c129f2a Fixes #2360 - Removed annoying log message
+b1ffffa Fixed #2525 - Wrong method being overridden in Red Hat services
+a88fc4d Fixing more tests broken from missing libraries
+9a356ab Fixing ActiveRecord Indirector tests to skip w/out Rails
+acc5a96 Fixing #2489 - queue integration tests are skipped w/out json
+1a5c5b3 Fixing #2508 - removing mention of ActiveRecord 2.3
+0cb9072 Fixing #2541 - file cache is more resilient to failure
+23948d0 vim: Mark puppetFunction values as contained
+79a4339 Add shellquote() function.
+79d705f Fixes #2499. Allows execs to specify an array for the returns parameter
+b611c34 Updated fix for #2481
+f385072 Revert "Fxied #2481 - Added status and restart overrides for Red Hat service provider."
+cc379b6 Fixed #2498 - logcheck update
+85a3633 Removed extraneous debugging
+bf94de9 Updated two more tests
+5b87dba Logs now assume resource params have metadata
+1410bed Adding metadata delegation from param to resource
+3ab3a5c Removing unnecessary debug output
+488e368 Adding integration tests for #2371 (backup refactor)
+f1406bf Adding many tests for #2371, and slightly refactoring
+8f60f0c Fixes for Redmine 2371.
+cd224c6 Fixes #2464, #2457. Deprecate reportserver for report_server. Add report_port setting. Add tests.
+401a9ec Fixing #2484 - "format missing" messages are better
+f6cc598 Fixes #2483 - Log only copies metadata from RAL objects
+7c4c00f Fixed #2486 - Missing require 'monitor' in parser_support.rb
+ea34ee6 Added R.I.Pienaar's extlookup.rb to the ext directory
+36d3f58 Added example conf/puppet-queue.conf
+967eb9f Fxied #2481 - Added status and restart overrides for Red Hat service provider.
+c702f76 rack: SSL Env vars can be in Request.env or ENV
+ca17b3c rack: don't directly use the forbidden HTTP_CONTENT_TYPE env var (fixes rack specification conformance)
+a002e58 Removing old filebucket test
+d8de446 Cleaning up tests for #2469
+266aafa default server in remote filebuckets
+1f8ef60 Fixes #2444 - Various JSON test failures
+11c0fb7 Fixed #2294 - Classes sometimes cannot be found
+7e5b562 Adding #2477 - puppet can apply provided catalogs
+97274ad Fixing problems my Feature refactor caused
+6fb8bf6 Fixing ruby warning in definition test
+b3545fc Fixed global deprecation error in useradd Unit tests
+dc24472 Adding a test for the Exec type
+58d9587 Speeding a test up through stubbing
+d4d8372 Fixing a small test by stubbing instead of mocking
+f7e1c36 Fixing a test broken by the regex features
+54a225d Fixing tests broken by caching autoload results
+1ce31b4 Migrating Handler base tests from test/ to spec/
+cc3f56a Migrating Feature tests to spec
+21d1d25 Fixing cron test to match new behaviour
+849fa67 Migrating tests to spec and removing an obsolete test
+6f458cc Logging the configuration version we're applying
+ac58e27 Configuration version information is now in logs
+6ed0103 Adding support for an external catalog version
+39320b8 Cleaning up duplication in another test file
+25fae5f Removing duplication in the test structure
+36c0662 Simplified Rakefile and moved tasks to tasks/rake directorya
+b45ccf8 Implement node matching with regexes
+58a73b5 Make sure node are referenced by their names
+3ebf148 Enhance selector and case statements to match with regexp
+ef68967 Fix #2033 - Allow regexp in if expression
+17e62b1 Add AST::Regex, an AST leaf node representing a regex
+4f9545f Add regexes and regex match operators to the parser
+0ccd259 Add regex, match and not match token to the lexer
+201ae59 Allow variable $0 to $9 to be interpolated, if ephemeral
+f357a91 Implement ephemeral scope variables
+d40ef29 Signed-off-by: Eric Sorenson <ahpook@gmail.com>
+6d22afb Modifying the REST client error to make server errors more clear
+21f477a Fixes #2472. Load Facter facts when ralsh is invoked, plus test.
+2e41edb Update CHANGELOG.git
+ebb5a1f Fixed ci_spec task for RubyGems 1.3.5
+b6b903e Fixes #2461. Provide new and old code paths for macosx_productversion_major with deprecation warning
+26b0c70 Fixing typo in two tests which caused them to always pass
+76fc2b1 Fixing #2440 - catalogs can now be compiled on demand
+832b6ff Exiting from app failures instead of raising
+4ea3f17 Minimal patch to fix #2290 (/tmp permissions)
+08ff9e8 Fix #2467 - rack: suggest putting puppet/lib at beginning of RUBYLIB search path
+fb60f90 Fix #2465 - Default auth information is confusing with no auth.conf
+0ca9b53 Fix #2459 - puppetdoc added namespace classes as RDoc modules instead of classes
+18b5d61 Fix #2429 - vim: class/define/node should only be followed by whitespace
+da828a4 Fix #2448 - fix the broken runit provider and tests
+3898436 Fixed #2405 - Mount parameter "dump" doesn't accept all valid values on FreeBSD
+9825bec Fixes #2362. Do not validate users/groups when supplied with numeric uid/gids
+450a19c Fix #2454 - Definition named after a module don't show in puppetdoc
+8551ece Fix #2453 - puppetdoc mixes long class names that look alike
+e3ee594 Fix #2422 & #2433 - make sure puppetdoc transform AST::Leaf boolean correctly
+b3b76df Fixing #2296 - overlapping recursions work again
+9120712 Fixing mocks to remove warnings
+eeec8e9 Fixing #2423 - no more strange dependency cycles
+7d40f9e Fixing #2443: Adding debugging guidance to dep cycle errors
+b4facb0 Fixing a test broken by changing the default os x package type
+b418921 Fixing selinux tests broken in the fix for #1963
+719e76b Fixing #2445 - fixing the mount test mock
+f13f08d Minor fix to URL for LDAP nodes documentation
+7c859a7 Fixing #2399 - removing client-side rrd graphs
+f6d6145 Fixing #2421 - file renaming errors now propagate
+db82523 Fixes #2438, get major OS X version from Facter and replace Puppet::Error invocations with fail builtin
+22145e7 Update install.rb to cope with all OS X versions, not just 10.5
+935c463 Fixing #2403 - provider specificity is richer and better
+d95b687 Fix #2439 - let puppetdoc use loaded_code
+ef5c4ae Fixed #2436 - Changed ralsh to use Puppet::Type.new and avoid deprecation notice
+0c18013 Fixes #2430 - Stock apache2.conf for passenger incorrect
+c383ceb Make pkgdmg default Darwin provider, make confines consistent on Darwin package providers.
+98599c4 Convert to using sbindir for OS X packages, clean out previous executables in bindir
+c659743 Fix #2425 - make sure client can contact CA server with REST
+17205bb Fix #2424 - take 2, make sure default mounts allow every clients
+f2c55cc Fix #2378 and #2391 tests
+8bbd8b4 Fix #2424 - File server can't find module in environment
+effaf80 Fix small typo in the fix for #2394
+a06094e Feature #2378 - Implement "thin_storeconfigs"
+b2a008e Fix #2391 - Exported resources never make to the storeconfigs db
+8f82407 Fix #2261 - Make sure query string parameters are properly escaped
+c86d44e Fixed #579 - puppet should try to clear solaris 10 services in maintenance state
+910a5e2 Fix #1963 - Failing to read /proc/mounts for selinux kills file downloads
+ba824e9 Fixing #2245 - provider lists are not lost on type reload
+eb40966 Ruby no longer clobbers puppet autoloading
+a42e878 deprecate NetInfo providers and examples, remove all NetInfo references and tests.
+22f5632 Fixed #2410 - default acl logs as info instead of warn.
+65b0137 Adding test for current auth config warning.
+74f5ad4 Fixed #2394 - warn once on module mount deprecation.
+f46a52a Add test for current module mount deprec warning.
+858d333 Fixes #2258,#2257,#2256. Maintain correct type for integers/booleans, allow correct values, and fix rule array handling
+44f127f Added Markdown mode to puppetdoc to output Markdown.
+8a8ce9d Excluded directories from rcov coverage report
+d152c5e Allow boolean value for boolean cli parameter
+911b490 Fix #2364 - Associates the correct comment to the right statement
+faefd92 Make sure the parser sees the correct line number
+869ec27 Fix #2366 - puppetdoc was parsing classes in the wrong order
+4c659b7 Added rcov coverage to Spec tests
+1fd98b1 Fixes #2367 - Mongrel::HTTPRequest returns a StringIO object
+8b09b83 Fix #2082 - puppetca shouldn't list revoked certificates
+ea66cf6 Fix #2348 - Allow authstore (and REST auth) to match allow/deny against opaque strings
+1e83aad Fix #2392 - use Content-Type for REST communication
+aaca17a Fixed #2293 - Added cron syntax X-Y/Z and '7' for sunday
+cddc365 Switching to LoadedCode from ASTSet
+fc1f8cd Adding a special class to handle loaded classes/defines/nodes
+325b8e4 Fix #2383, an incompatibility with early ruby 1.8 versions
+46112da Fixing #2238 In some cases blank? is not available on String.
+cdd1662 Fixing #2238 - Deal with nil hash keys from mongrel params
+769c8aa Final fix to CI test rakes
+a6816ff Set ENV['PATH'] to an empty string if non-existent
+64a4720 Fix to CI rake tasks
+5680cd5 Fixing #2197 - daemontools tests now pass
+603b9cf Change the diff default output to "unified"
+9bc9b5c Added missing colon to suntab
+0f2d70d Fixed #2087 and refactored the code that gets the smf service state
+
0.25.0beta2
===========
3f070c1 Using the logging utilities to clean up module warnings
diff --git a/Rakefile b/Rakefile
index 67d5ef4da..9c7e61927 100644
--- a/Rakefile
+++ b/Rakefile
@@ -41,13 +41,14 @@ task :spec do
require 'spec'
require 'spec/rake/spectask'
begin
- require 'rcov'
+# require 'rcov'
rescue LoadError
end
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--format','s', '--loadby','mtime']
t.spec_files = FileList['spec/**/*.rb']
+ t.fail_on_error = false
if defined?(Rcov)
t.rcov = true
t.rcov_opts = ['--exclude', 'spec/*,test/*,results/*,/usr/lib/*,/usr/local/lib/*']
diff --git a/conf/osx/createpackage.sh b/conf/osx/createpackage.sh
index d27ef0e7a..563b69cbd 100755
--- a/conf/osx/createpackage.sh
+++ b/conf/osx/createpackage.sh
@@ -54,6 +54,17 @@ function install_puppet() {
chown -R root:admin "${pkgroot}"
}
+function install_docs() {
+ echo "Installing docs to ${pkgroot}"
+ docdir="${pkgroot}/usr/share/doc/puppet"
+ mkdir -p "${docdir}"
+ for docfile in CHANGELOG CHANGELOG.old COPYING LICENSE README README.queueing README.rst; do
+ install -m 0644 "${puppet_root}/${docfile}" "${docdir}"
+ done
+ chown -R root:wheel "${docdir}"
+ chmod 0755 "${docdir}"
+}
+
function get_puppet_version() {
puppet_version=$(RUBYLIB="${pkgroot}/${SITELIBDIR}:${RUBYLIB}" ruby -e "require 'puppet'; puts Puppet.version")
}
@@ -156,6 +167,7 @@ function main() {
fi
install_puppet
+ install_docs
get_puppet_version
if [ ! "${puppet_version}" ]; then
diff --git a/conf/osx/preflight b/conf/osx/preflight
index 3a6109e65..8220d02a3 100755
--- a/conf/osx/preflight
+++ b/conf/osx/preflight
@@ -11,6 +11,10 @@
/bin/rm -Rf "${3}{SITELIBDIR}/puppet"
/bin/rm -Rf "${3}{SITELIBDIR}/puppet.rb"
+# remove old doc files
+
+/bin/rm -Rf "${3}/usr/share/doc/puppet"
+
# In puppet 0.24.x these executables lived in bindir, but in 0.25.x they
# have been moved to sbindir. This cleans out old ones before installing.
/bin/rm -Rf "${3}{BINDIR}/puppetca"
diff --git a/conf/redhat/client.init b/conf/redhat/client.init
index a5ac08d87..0c98383d5 100644
--- a/conf/redhat/client.init
+++ b/conf/redhat/client.init
@@ -27,6 +27,9 @@ PUPPET_OPTS=""
[ -n "$PUPPET_LOG" ] && PUPPET_OPTS="${PUPPET_OPTS} --logdest=${PUPPET_LOG}"
[ -n "$PUPPET_PORT" ] && PUPPET_OPTS="${PUPPET_OPTS} --masterport=${PUPPET_PORT}"
+# Determine if we can use the -p option to killproc. RHEL < 5 can't.
+killproc | grep -q -- '-p' 2>/dev/null && killopts="-p $pidfile"
+
# Figure out if the system just booted. Let's assume
# boot doesn't take longer than 5 minutes
## Not used for now
@@ -43,7 +46,7 @@ start() {
stop() {
echo -n $"Stopping puppet: "
- killproc $puppetd
+ killproc $killopts $puppetd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
@@ -51,7 +54,7 @@ stop() {
reload() {
echo -n $"Restarting puppet: "
- killproc $puppetd -HUP
+ killproc $killopts $puppetd -HUP
RETVAL=$?
echo
return $RETVAL
diff --git a/conf/redhat/server.init b/conf/redhat/server.init
index 4bc44b9fb..4f4420683 100644
--- a/conf/redhat/server.init
+++ b/conf/redhat/server.init
@@ -13,6 +13,7 @@ PATH=/usr/bin:/sbin:/bin:/usr/sbin
export PATH
lockfile=/var/lock/subsys/puppetmaster
+pidfile=/var/run/puppet/puppetmasterd.pid
# Source function library.
. /etc/rc.d/init.d/functions
@@ -71,8 +72,9 @@ stop() {
ret=$?; [ $ret != 0 ] && RETVAL=$ret
done
else
- killproc $PUPPETMASTER
- RETVAL=$?
+ killproc | grep -q -- '-p' 2>/dev/null && killopts="-p $pidfile"
+ killproc $killopts $PUPPETMASTER
+ RETVAL=$?
fi
echo
[ $RETVAL -eq 0 ] && rm -f "$lockfile"
diff --git a/ext/puppetlast b/ext/puppetlast
index e52529dd7..e9496760a 100755
--- a/ext/puppetlast
+++ b/ext/puppetlast
@@ -4,6 +4,7 @@
# AJ "Fujin" Christensen <aj@junglist.gen.nz>
#
require 'puppet'
+require 'time'
Puppet[:config] = "/etc/puppet/puppet.conf"
Puppet.parse_config
@@ -11,5 +12,5 @@ Puppet[:name] = "puppetmasterd"
Puppet::Node::Facts.terminus_class = :yaml
Puppet::Node::Facts.search("*").sort { |a,b| a.name <=> b.name }.each do |node|
- puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}checked in #{((Time.now - node.values[:_timestamp]) / 60).floor} minutes ago"
+ puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}checked in #{((Time.now - Time.parse(node.values[:_timestamp])) / 60).floor} minutes ago"
end
diff --git a/ext/rack/README b/ext/rack/README
index 3bdcca53f..d05d4026f 100644
--- a/ext/rack/README
+++ b/ext/rack/README
@@ -43,7 +43,7 @@ Make sure puppetmasterd ran at least once, so the CA & SSL certificates
got set up.
Requirements:
- Passenger version 2.2.2 or newer***
+ Passenger version 2.2.2 or 2.2.5 or newer***
Rack version 1.0.0
Apache 2.x
SSL Module loaded
@@ -68,6 +68,6 @@ config.ru. Therefore, config.ru shall be owned by the puppet user.
*** Important note about Passenger versions:
2.2.2 is known to work.
2.2.3-2.2.4 are known to *NOT* work.
- 2.2.5 (when it is released) is expected to work properly again.
+ 2.2.5 works again when used with Puppet 0.25.2+.
Passenger installation doc: http://www.modrails.com/install.html
diff --git a/ext/regexp_nodes/classes/databases b/ext/regexp_nodes/classes/databases
new file mode 100644
index 000000000..2dd052b0c
--- /dev/null
+++ b/ext/regexp_nodes/classes/databases
@@ -0,0 +1,2 @@
+db\d{2}
+mysql
diff --git a/ext/regexp_nodes/classes/webservers b/ext/regexp_nodes/classes/webservers
new file mode 100644
index 000000000..1df02bcab
--- /dev/null
+++ b/ext/regexp_nodes/classes/webservers
@@ -0,0 +1,2 @@
+^(web|www)
+leterel
diff --git a/ext/regexp_nodes/parameters/environment/prod b/ext/regexp_nodes/parameters/environment/prod
new file mode 100644
index 000000000..dd3f100c9
--- /dev/null
+++ b/ext/regexp_nodes/parameters/environment/prod
@@ -0,0 +1 @@
+\d{3}$
diff --git a/ext/regexp_nodes/parameters/environment/qa b/ext/regexp_nodes/parameters/environment/qa
new file mode 100644
index 000000000..85fccca80
--- /dev/null
+++ b/ext/regexp_nodes/parameters/environment/qa
@@ -0,0 +1,3 @@
+^qa-
+^qa2-
+^qa3-
diff --git a/ext/regexp_nodes/regexp_nodes.rb b/ext/regexp_nodes/regexp_nodes.rb
new file mode 100644
index 000000000..1f4fdbc3a
--- /dev/null
+++ b/ext/regexp_nodes/regexp_nodes.rb
@@ -0,0 +1,215 @@
+#!/usr/bin/env ruby
+
+# = Synopsis
+# This is an external node classifier script, after
+# http://reductivelabs.com/trac/puppet/wiki/ExternalNodes
+#
+# = Usage
+# regexp_nodes.rb <host>
+#
+# = Description
+# This classifier implements filesystem autoloading: It looks through classes
+# and parameters subdirectories, looping through each file it finds there - the
+# contents are a regexp-per-line which, if they match the hostname passed us as
+# ARGV[0], will cause a class or parameter named the same thing as the file to
+# be set.
+#
+# = Examples
+# In the distribution there are two subdirectories test_classes/ and
+# test_parameters, which are passed as parameters to MyExternalNode.new.
+# test_classes/database will set the 'database' class for any hostnames
+# matching %r{db\d{2}} (that is, 'db' followed by two digits) or with 'mysql'
+# anywhere in the hostname. Similarly, hosts beginning with 'www' or 'web'
+# or the hostname 'leterel' (my workstation) will be assigned the 'webserver'
+# class.
+#
+# Under test_parameters/ there is one subdirectory 'environment' which
+# sets the a parameter called 'environment' to the value 'prod' for production
+# hosts (whose hostnames always end with three numbers for us), 'qa' for
+# anything that starts with 'qa-' 'qa2-' or 'qa3-', and 'sandbox' for any
+# development machines which are, naturally, named after Autechre songs.
+#
+#
+# = Author
+# Eric Sorenson <esorenson@apple.com>
+
+
+# we need yaml or there's not much point in going on
+require 'yaml'
+
+# Sets are like arrays but automatically de-duplicate elements
+require 'set'
+
+# set up some nice logging
+require 'logger'
+# XXX flip this for production vs local sandbox
+# $LOG = Logger.new("/var/puppet/log/extnodes.log")
+# $LOG.level = Logger::FATAL
+$LOG = Logger.new($stderr)
+$LOG.level = Logger::DEBUG
+
+# paths for files we use will be relative to this directory
+# XXX flip this for production vs local sandbox
+# WORKINGDIR = "/var/puppet/bin"
+WORKINGDIR = Dir.pwd
+
+# This class holds all the methods for creating and accessing the properties
+# of an external node. There are really only two public methods: initialize()
+# and a special version of to_yaml()
+
+class ExternalNode
+ # Make these instance variables get/set-able with eponymous methods
+ attr_accessor :classes, :parameters, :hostname
+
+ # initialize() takes three arguments:
+ # hostname:: usually passed in via ARGV[0] but it could be anything
+ # classdir:: directory under WORKINGDIR to look for files named after
+ # classes
+ # parameterdir:: directory under WORKINGDIR to look for directories to set
+ # parameters
+ def initialize(hostname, classdir = 'classes/', parameterdir = 'parameters/')
+ # instance variables that contain the lists of classes and parameters
+ @hostname
+ @classes = Set.new ["baseclass"]
+ @parameters = Hash.new("unknown") # sets a default value of "unknown"
+
+ self.parse_argv(hostname)
+ self.match_classes(WORKINGDIR + "/" + classdir)
+ self.match_parameters(WORKINGDIR + "/" + parameterdir)
+ end
+
+ # private method called by initialize() which sanity-checks our hostname.
+ # good candidate for overriding in a subclass if you need different checks
+ def parse_argv(hostname)
+ if hostname =~ /^([-\w]+?)\.([-\w\.]+)/ # non-greedy up to the first . is hostname
+ @hostname = $1
+ elsif hostname =~ /^([-\w]+)$/ # sometimes puppet's @name is just a name
+ @hostname = hostname
+ else
+ $LOG.fatal("didn't receive parsable hostname, got: [#{hostname}]")
+ exit(1)
+ end
+ end
+
+ # to_yaml massages a copy of the object and outputs clean yaml so we don't
+ # feed weird things back to puppet []<
+ def to_yaml
+ classes = self.classes.to_a
+ if self.parameters.empty? # otherwise to_yaml prints "parameters: {}"
+ parameters = nil
+ else
+ parameters = self.parameters
+ end
+ ({ 'classes' => classes, 'parameters' => parameters}).to_yaml
+ end
+
+ # Private method that expects an absolute path to a file and a string to
+ # match - it returns true if the string was matched by any of the lines in
+ # the file
+ def matched_in_patternfile?(filepath, matchthis)
+
+ patternlist = []
+
+ begin
+ open(filepath).each { |l|
+ pattern = %r{#{l.chomp!}}
+ patternlist << pattern
+ $LOG.debug("appending [#{pattern}] to patternlist for [#{filepath}]")
+ }
+ rescue Exception
+ $LOG.fatal("Problem reading #{filepath}: #{$!}")
+ exit(1)
+ end
+
+ $LOG.debug("list of patterns for #{filepath}: #{patternlist}")
+
+ if matchthis =~ Regexp.union(patternlist)
+ $LOG.debug("matched #{$~.to_s} in #{matchthis}, returning true")
+ return true
+
+ else # hostname didn't match anything in patternlist
+ $LOG.debug("#{matchthis} unmatched, returning false")
+ return nil
+ end
+
+ end # def
+
+ # private method - takes a path to look for files, iterates through all
+ # readable, regular files it finds, and matches this instance's @hostname
+ # against each line; if any match, the class will be set for this node.
+ def match_classes(fullpath)
+ Dir.foreach(fullpath) do |patternfile|
+ filepath = "#{fullpath}/#{patternfile}"
+ next unless File.file?(filepath) and
+ File.readable?(filepath)
+ $LOG.debug("Attempting to match [#{@hostname}] in [#{filepath}]")
+ if matched_in_patternfile?(filepath,@hostname)
+ @classes << patternfile.to_s
+ $LOG.debug("Appended #{patternfile.to_s} to classes instance variable")
+ end # if
+ end # Dir.foreach
+ end # def
+
+ # Parameters are handled slightly differently; we make another level of
+ # directories to get the parameter name, then use the names of the files
+ # contained in there for the values of those parameters.
+ #
+ # ex: cat /var/puppet/bin/parameters/environment/production
+ # ^prodweb
+ # would set parameters["environment"] = "production" for prodweb001
+ def match_parameters(fullpath)
+ Dir.foreach(fullpath) do |parametername|
+
+ filepath = "#{fullpath}/#{parametername}"
+ next if File.basename(filepath) =~ /^\./ # skip over dotfiles
+
+ next unless File.directory?(filepath) and
+ File.readable?(filepath) # skip over non-directories
+
+ $LOG.debug "Considering contents of #{filepath}"
+
+ Dir.foreach("#{filepath}") do |patternfile|
+ secondlevel = "#{filepath}/#{patternfile}"
+ $LOG.debug "Found parameters patternfile at #{secondlevel}"
+ next unless File.file?(secondlevel) and
+ File.readable?(secondlevel)
+ $LOG.debug("Attempting to match [#{@hostname}] in [#{secondlevel}]")
+ if matched_in_patternfile?(secondlevel, @hostname)
+ @parameters[ parametername.to_s ] = patternfile.to_s
+ $LOG.debug("Set @parameters[#{parametername.to_s}] = #{patternfile.to_s}")
+ end # if
+ end # Dir.foreach #{filepath}
+ end # Dir.foreach #{fullpath}
+ end # def
+
+end # Class
+
+# Logic for local hacks that don't fit neatly into the autoloading model can
+# happen as we initialize a subclass
+class MyExternalNode < ExternalNode
+
+ def initialize(hostname, classdir = 'classes/', parameterdir = 'parameters/')
+
+ super
+
+ # Set "hostclass" parameter based on hostname,
+ # stripped of leading environment prefix and numeric suffix
+ if @hostname =~ /^(\w*?)-?(\D+)(\d{2,3})$/
+ match = Regexp.last_match
+
+ hostclass = match[2]
+ $LOG.debug("matched hostclass #{hostclass}")
+ @parameters[ "hostclass" ] = hostclass
+ else
+ $LOG.debug("hostclass couldn't figure out class from #{@hostname}")
+ end # if
+ end # def
+
+end # Class
+
+
+# Here we begin actual execution by calling methods defined above
+
+mynode = MyExternalNode.new(ARGV[0], classes = 'test_classes', parameters = 'test_parameters')
+
+puts mynode.to_yaml
diff --git a/lib/puppet/agent.rb b/lib/puppet/agent.rb
index 7bd97415f..09607372f 100644
--- a/lib/puppet/agent.rb
+++ b/lib/puppet/agent.rb
@@ -52,7 +52,7 @@ class Puppet::Agent
with_client do |client|
begin
sync.synchronize { lock { result = client.run(*args) } }
- rescue => detail
+ rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not run %s: %s" % [client_class, detail]
end
@@ -124,7 +124,7 @@ class Puppet::Agent
def with_client
begin
@client = client_class.new
- rescue => detail
+ rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not create instance of %s: %s" % [client_class, detail]
return
diff --git a/lib/puppet/application/puppetd.rb b/lib/puppet/application/puppetd.rb
index c1f733183..9302cf105 100644
--- a/lib/puppet/application/puppetd.rb
+++ b/lib/puppet/application/puppetd.rb
@@ -137,7 +137,7 @@ Puppet::Application.new(:puppetd) do
options[:verbose] = true
options[:onetime] = true
options[:detailed_exitcodes] = true
- options[:waitforcert] = 0
+ options[:waitforcert] = 0 unless @explicit_waitforcert
end
# Handle the logging settings.
@@ -172,13 +172,6 @@ Puppet::Application.new(:puppetd) do
exit(14)
end
- # FIXME: we should really figure out how to distribute the CRL
- # to clients. In the meantime, we just disable CRL checking if
- # the CRL file doesn't exist
- unless File::exist?(Puppet[:cacrl])
- Puppet[:cacrl] = 'false'
- end
-
handlers = nil
if options[:serve].empty?
diff --git a/lib/puppet/application/puppetdoc.rb b/lib/puppet/application/puppetdoc.rb
index a5496ccee..0a4e0c3c3 100644
--- a/lib/puppet/application/puppetdoc.rb
+++ b/lib/puppet/application/puppetdoc.rb
@@ -66,8 +66,9 @@ Puppet::Application.new(:puppetdoc) do
exit_code = 0
files = []
unless @manifest
- files += Puppet[:modulepath].split(':').collect { |p| File.expand_path(p) }
- files += Puppet[:manifestdir].split(':').collect { |p| File.expand_path(p) }
+ env = Puppet::Node::Environment.new
+ files += env.modulepath
+ files += env.manifestdir
end
files += ARGV
Puppet.info "scanning: %s" % files.inspect
@@ -191,7 +192,7 @@ Puppet::Application.new(:puppetdoc) do
end
end
- def setup_rdoc
+ def setup_rdoc(dummy_argument=:work_arround_for_ruby_GC_bug)
# consume the unknown options
# and feed them as settings
if @unknown_args.size > 0
diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb
index b63df0754..72aef91c0 100644
--- a/lib/puppet/configurer.rb
+++ b/lib/puppet/configurer.rb
@@ -93,7 +93,7 @@ class Puppet::Configurer
duration = thinmark do
result = catalog_class.find(name, fact_options.merge(:ignore_cache => true))
end
- rescue => detail
+ rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not retrieve catalog from remote server: %s" % detail
end
@@ -123,6 +123,7 @@ class Puppet::Configurer
# Convert a plain resource catalog into our full host catalog.
def convert_catalog(result, duration)
catalog = result.to_ral
+ catalog.finalize
catalog.retrieval_duration = duration
catalog.host_config = true
catalog.write_class_file
@@ -133,7 +134,12 @@ class Puppet::Configurer
# This just passes any options on to the catalog,
# which accepts :tags and :ignoreschedules.
def run(options = {})
- prepare()
+ begin
+ prepare()
+ rescue Exception => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Failed to prepare catalog: %s" % detail
+ end
if catalog = options[:catalog]
options.delete(:catalog)
diff --git a/lib/puppet/configurer/fact_handler.rb b/lib/puppet/configurer/fact_handler.rb
index 43e9f35f4..cbb627680 100644
--- a/lib/puppet/configurer/fact_handler.rb
+++ b/lib/puppet/configurer/fact_handler.rb
@@ -11,14 +11,13 @@ module Puppet::Configurer::FactHandler
end
def find_facts
- reload_facter()
-
# This works because puppetd configures Facts to use 'facter' for
# finding facts and the 'rest' terminus for caching them. Thus, we'll
# compile them and then "cache" them on the server.
begin
+ reload_facter()
Puppet::Node::Facts.find(Puppet[:certname])
- rescue => detail
+ rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
raise Puppet::Error, "Could not retrieve local facts: %s" % detail
end
@@ -29,11 +28,11 @@ module Puppet::Configurer::FactHandler
#format = facts.class.default_format
# Hard-code yaml, because I couldn't get marshal to work.
- format = :yaml
+ format = :b64_zlib_yaml
text = facts.render(format)
- return {:facts_format => format, :facts => CGI.escape(text)}
+ return {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(text)}
end
# Retrieve facts from the central server.
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 590de83fd..050fcaa7e 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -527,6 +527,18 @@ module Puppet
authority requests. It's a separate server because it cannot
and does not need to horizontally scale."],
:ca_port => ["$masterport", "The port to use for the certificate authority."],
+ :catalog_format => {
+ :default => "",
+ :desc => "(Deprecated for 'preferred_serialization_format') What format to
+ use to dump the catalog. Only supports 'marshal' and 'yaml'. Only
+ matters on the client, since it asks the server for a specific format.",
+ :hook => proc { |value|
+ if value
+ Puppet.warning "Setting 'catalog_format' is deprecated; use 'preferred_serialization_format' instead."
+ Puppet.settings[:preferred_serialization_format] = value
+ end
+ }
+ },
:preferred_serialization_format => ["pson", "The preferred means of serializing
ruby instances for passing over the wire. This won't guarantee that all
instances will be serialized using this method, since not all classes
diff --git a/lib/puppet/external/pson/common.rb b/lib/puppet/external/pson/common.rb
index 71b85ce54..87bce988b 100644
--- a/lib/puppet/external/pson/common.rb
+++ b/lib/puppet/external/pson/common.rb
@@ -48,7 +48,7 @@ module PSON
case
when c.empty? then p
when p.const_defined?(c) then p.const_get(c)
- else raise ArgumentError, "can't find const #{path}"
+ else raise ArgumentError, "can't find const for unregistered document type #{path}"
end
end
end
diff --git a/lib/puppet/external/pson/pure.rb b/lib/puppet/external/pson/pure.rb
index 43f39b2a6..7bb18aa70 100644
--- a/lib/puppet/external/pson/pure.rb
+++ b/lib/puppet/external/pson/pure.rb
@@ -11,8 +11,8 @@ module PSON
UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
UTF8toUTF16.iconv('no bom')
rescue LoadError
- raise MissingUnicodeSupport,
- "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
+ # We actually don't care
+ Puppet.warning "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
rescue Errno::EINVAL, Iconv::InvalidEncoding
# Iconv doesn't support big endian utf-16. Let's try to hack this manually
# into the converters.
diff --git a/lib/puppet/file_serving/base.rb b/lib/puppet/file_serving/base.rb
index c82bb1992..a7ab9b66e 100644
--- a/lib/puppet/file_serving/base.rb
+++ b/lib/puppet/file_serving/base.rb
@@ -22,7 +22,7 @@ class Puppet::FileServing::Base
end
# Return the full path to our file. Fails if there's no path set.
- def full_path
+ def full_path(dummy_argument=:work_arround_for_ruby_GC_bug)
(if relative_path.nil? or relative_path == "" or relative_path == "."
path
else
@@ -74,4 +74,19 @@ class Puppet::FileServing::Base
end
File.send(@stat_method, full_path())
end
+
+ def to_pson_data_hash
+ {
+ # No 'document_type' since we don't send these bare
+ 'data' => {
+ 'path' => @path,
+ 'relative_path' => @relative_path,
+ 'links' => @links
+ },
+ 'metadata' => {
+ 'api_version' => 1
+ }
+ }
+ end
+
end
diff --git a/lib/puppet/file_serving/configuration.rb b/lib/puppet/file_serving/configuration.rb
index ac54a7a8a..9034caed1 100644
--- a/lib/puppet/file_serving/configuration.rb
+++ b/lib/puppet/file_serving/configuration.rb
@@ -96,9 +96,9 @@ class Puppet::FileServing::Configuration
def mk_default_mounts
@mounts["modules"] ||= Mount::Modules.new("modules")
- @mounts["modules"].allow('*')
+ @mounts["modules"].allow('*') if @mounts["modules"].empty?
@mounts["plugins"] ||= Mount::Plugins.new("plugins")
- @mounts["plugins"].allow('*')
+ @mounts["plugins"].allow('*') if @mounts["plugins"].empty?
end
# Read the configuration file.
diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb
index 335dad497..275a090eb 100644
--- a/lib/puppet/file_serving/metadata.rb
+++ b/lib/puppet/file_serving/metadata.rb
@@ -71,8 +71,47 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::Base
end
end
- def initialize(*args)
- @checksum_type = "md5"
- super
+ def initialize(path,data={})
+ @owner = data.delete('owner')
+ @group = data.delete('group')
+ @mode = data.delete('mode')
+ if checksum = data.delete('checksum')
+ @checksum_type = checksum['type']
+ @checksum = checksum['value']
+ end
+ @checksum_type ||= "md5"
+ @ftype = data.delete('type')
+ @destination = data.delete('destination')
+ super(path,data)
+ end
+
+ PSON.register_document_type('FileMetadata',self)
+ def to_pson_data_hash
+ {
+ 'document_type' => 'FileMetadata',
+ 'data' => super['data'].update({
+ 'owner' => owner,
+ 'group' => group,
+ 'mode' => mode,
+ 'checksum' => {
+ 'type' => checksum_type,
+ 'value' => checksum
+ },
+ 'type' => ftype,
+ 'destination' => destination,
+ }),
+ 'metadata' => {
+ 'api_version' => 1
+ }
+ }
+ end
+
+ def to_pson(*args)
+ to_pson_data_hash.to_pson(*args)
+ end
+
+ def self.from_pson(data)
+ new(data.delete('path'), data)
end
+
end
diff --git a/lib/puppet/indirector/catalog/active_record.rb b/lib/puppet/indirector/catalog/active_record.rb
index e3b56ece6..575ce72fb 100644
--- a/lib/puppet/indirector/catalog/active_record.rb
+++ b/lib/puppet/indirector/catalog/active_record.rb
@@ -30,6 +30,11 @@ class Puppet::Resource::Catalog::ActiveRecord < Puppet::Indirector::ActiveRecord
host.merge_resources(catalog.vertices)
host.last_compile = Time.now
+ if node = Puppet::Node.find(catalog.name)
+ host.ip = node.parameters["ipaddress"]
+ host.environment = node.environment
+ end
+
host.save
end
end
diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb
index 9df71fcac..6c6cbc6be 100644
--- a/lib/puppet/indirector/facts/facter.rb
+++ b/lib/puppet/indirector/facts/facter.rb
@@ -29,7 +29,7 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code
Timeout::timeout(self.timeout) do
load file
end
- rescue => detail
+ rescue Exception => detail
Puppet.warning "Could not load fact file %s: %s" % [fqfile, detail]
end
end
diff --git a/lib/puppet/indirector/ldap.rb b/lib/puppet/indirector/ldap.rb
index 7485bd932..51bab0e6e 100644
--- a/lib/puppet/indirector/ldap.rb
+++ b/lib/puppet/indirector/ldap.rb
@@ -40,7 +40,7 @@ class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
found = true
yield entry
end
- rescue => detail
+ rescue Exception => detail
if count == 0
# Try reconnecting to ldap if we get an exception and we haven't yet retried.
count += 1
diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb
index 4600a0dd5..dd8cebfac 100644
--- a/lib/puppet/indirector/node/ldap.rb
+++ b/lib/puppet/indirector/node/ldap.rb
@@ -73,7 +73,7 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
# The attributes that Puppet will stack as array over the full
# hierarchy.
- def stacked_attributes
+ def stacked_attributes(dummy_argument=:work_arround_for_ruby_GC_bug)
Puppet[:ldapstackedattrs].split(/\s*,\s*/)
end
diff --git a/lib/puppet/network/authstore.rb b/lib/puppet/network/authstore.rb
index ab31faec8..fb3d0145b 100755
--- a/lib/puppet/network/authstore.rb
+++ b/lib/puppet/network/authstore.rb
@@ -63,6 +63,11 @@ module Puppet
@globalallow
end
+ # does this auth store has any rules?
+ def empty?
+ @globalallow.nil? && @declarations.size == 0
+ end
+
def initialize
@globalallow = nil
@declarations = []
diff --git a/lib/puppet/network/format_handler.rb b/lib/puppet/network/format_handler.rb
index 2ffbcef3d..e508a0283 100644
--- a/lib/puppet/network/format_handler.rb
+++ b/lib/puppet/network/format_handler.rb
@@ -129,6 +129,8 @@ module Puppet::Network::FormatHandler
if list.include?(preferred_format)
list.delete(preferred_format)
list.unshift(preferred_format)
+ else
+ Puppet.warning "Value of 'preferred_serialization_format' ('#{preferred_format}') is invalid, using default ('#{list.first}')"
end
list
end
diff --git a/lib/puppet/network/formats.rb b/lib/puppet/network/formats.rb
index df6ef399c..010c23521 100644
--- a/lib/puppet/network/formats.rb
+++ b/lib/puppet/network/formats.rb
@@ -39,6 +39,56 @@ Puppet::Network::FormatHandler.create(:yaml, :mime => "text/yaml") do
end
end
+# This is a "special" format which is used for the moment only when sending facts
+# as REST GET parameters (see Puppet::Configurer::FactHandler).
+# This format combines a yaml serialization, then zlib compression and base64 encoding.
+Puppet::Network::FormatHandler.create(:b64_zlib_yaml, :mime => "text/b64_zlib_yaml") do
+ require 'base64'
+ require 'zlib'
+
+ def intern(klass, text)
+ decode(text)
+ end
+
+ def intern_multiple(klass, text)
+ decode(text)
+ end
+
+ def render(instance)
+ yaml = instance.to_yaml
+
+ yaml = encode(fixup(yaml)) unless yaml.nil?
+ yaml
+ end
+
+ def render_multiple(instances)
+ yaml = instances.to_yaml
+
+ yaml = encode(fixup(yaml)) unless yaml.nil?
+ yaml
+ end
+
+ # Because of yaml issue in ruby 1.8.1...
+ def supported?(klass)
+ RUBY_VERSION != '1.8.1'
+ end
+
+ # fixup invalid yaml as per:
+ # http://redmine.ruby-lang.org/issues/show/1331
+ def fixup(yaml)
+ yaml.gsub!(/((?:&id\d+\s+)?!ruby\/object:.*?)\s*\?/) { "? #{$1}" }
+ yaml
+ end
+
+ def encode(text)
+ Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION))
+ end
+
+ def decode(yaml)
+ YAML.load(Zlib::Inflate.inflate(Base64.decode64(yaml)))
+ end
+end
+
Puppet::Network::FormatHandler.create(:marshal, :mime => "text/marshal") do
# Marshal doesn't need the class name; it's serialized.
diff --git a/lib/puppet/network/http/rack/httphandler.rb b/lib/puppet/network/http/rack/httphandler.rb
index 31aa8371e..e14206850 100644
--- a/lib/puppet/network/http/rack/httphandler.rb
+++ b/lib/puppet/network/http/rack/httphandler.rb
@@ -12,23 +12,5 @@ class Puppet::Network::HTTP::RackHttpHandler
raise NotImplementedError, "Your RackHttpHandler subclass is supposed to override service(request)"
end
- def ssl_client_header(request)
- env_or_request_env(Puppet[:ssl_client_header], request)
- end
-
- def ssl_client_verify_header(request)
- env_or_request_env(Puppet[:ssl_client_verify_header], request)
- end
-
- # Older Passenger versions passed all Environment vars in app(env),
- # but since 2.2.3 they (some?) are really in ENV.
- # Mongrel, etc. may also still use request.env.
- def env_or_request_env(var, request)
- if ENV.include?(var)
- ENV[var]
- else
- request.env[var]
- end
- end
end
diff --git a/lib/puppet/network/http/rack/rest.rb b/lib/puppet/network/http/rack/rest.rb
index bdca651d1..104751271 100644
--- a/lib/puppet/network/http/rack/rest.rb
+++ b/lib/puppet/network/http/rack/rest.rb
@@ -63,11 +63,11 @@ class Puppet::Network::HTTP::RackREST < Puppet::Network::HTTP::RackHttpHandler
result[:ip] = request.ip
# if we find SSL info in the headers, use them to get a hostname.
- # try this with :ssl_client_header.
- # For Apache you need special configuration, see ext/rack/README.
- if dn = ssl_client_header(request) and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
+ # try this with :ssl_client_header, which defaults should work for
+ # Apache with StdEnvVars.
+ if dn = request.env[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
result[:node] = dn_matchdata[1].to_str
- result[:authenticated] = (ssl_client_verify_header(request) == 'SUCCESS')
+ result[:authenticated] = (request.env[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
else
result[:node] = resolve_node(result)
result[:authenticated] = false
diff --git a/lib/puppet/network/http/rack/xmlrpc.rb b/lib/puppet/network/http/rack/xmlrpc.rb
index 9d0f486bc..4fc9e82fc 100644
--- a/lib/puppet/network/http/rack/xmlrpc.rb
+++ b/lib/puppet/network/http/rack/xmlrpc.rb
@@ -43,11 +43,11 @@ class Puppet::Network::HTTP::RackXMLRPC < Puppet::Network::HTTP::RackHttpHandler
ip = request.ip
# if we find SSL info in the headers, use them to get a hostname.
- # try this with :ssl_client_header.
- # For Apache you need special configuration, see ext/rack/README.
- if dn = ssl_client_header(request) and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
+ # try this with :ssl_client_header, which defaults should work for
+ # Apache with StdEnvVars.
+ if dn = request.env[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
node = dn_matchdata[1].to_str
- authenticated = (ssl_client_verify_header(request) == 'SUCCESS')
+ authenticated = (request.env[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
else
begin
node = Resolv.getname(ip)
diff --git a/lib/puppet/network/http_server/webrick.rb b/lib/puppet/network/http_server/webrick.rb
index a863d3a20..2dae9ccd8 100644
--- a/lib/puppet/network/http_server/webrick.rb
+++ b/lib/puppet/network/http_server/webrick.rb
@@ -21,13 +21,10 @@ module Puppet
# with them, with flags appropriate for checking client
# certificates for revocation
def x509store
- if Puppet[:cacrl] == 'false'
+ unless File.exist?(Puppet[:cacrl])
# No CRL, no store needed
return nil
end
- unless File.exist?(Puppet[:cacrl])
- raise Puppet::Error, "Could not find CRL; set 'cacrl' to 'false' to disable CRL usage"
- end
crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
store = OpenSSL::X509::Store.new
store.purpose = OpenSSL::X509::PURPOSE_ANY
diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb
index 133f22c77..94f899200 100644
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@ -55,15 +55,7 @@ class Puppet::Node::Environment
if ENV["PUPPETLIB"]
dirs = ENV["PUPPETLIB"].split(File::PATH_SEPARATOR) + dirs
end
- dirs.collect do |dir|
- if dir !~ /^#{File::SEPARATOR}/
- File.join(Dir.getwd, dir)
- else
- dir
- end
- end.find_all do |p|
- p =~ /^#{File::SEPARATOR}/ && FileTest.directory?(p)
- end
+ validate_dirs(dirs)
end
# Return all modules from this environment.
@@ -73,7 +65,26 @@ class Puppet::Node::Environment
module_names.collect { |path| Puppet::Module.new(path, self) rescue nil }.compact
end
+ # Cache the manifestdir, so that we aren't searching through
+ # all known directories all the time.
+ cached_attr(:manifestdir, :ttl => Puppet[:filetimeout]) do
+ validate_dirs(self[:manifestdir].split(File::PATH_SEPARATOR))
+ end
+
def to_s
name.to_s
end
+
+ def validate_dirs(dirs)
+ dirs.collect do |dir|
+ if dir !~ /^#{File::SEPARATOR}/
+ File.join(Dir.getwd, dir)
+ else
+ dir
+ end
+ end.find_all do |p|
+ p =~ /^#{File::SEPARATOR}/ && FileTest.directory?(p)
+ end
+ end
+
end
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index f4086671d..58a91477a 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -293,6 +293,13 @@ class Puppet::Parameter
define_method(:unmunge, &block)
end
+ # Optionaly convert the value to a canonical form so that it will
+ # be found in hashes, etc. Mostly useful for namevars.
+ def to_canonicalize(&block)
+ metaclass = (class << self; self; end)
+ metaclass.send(:define_method,:canonicalize,&block)
+ end
+
# Mark whether we're the namevar.
def isnamevar
@isnamevar = true
@@ -464,10 +471,19 @@ class Puppet::Parameter
value
end
+ # Assume the value is already in canonical form by default
+ def self.canonicalize(value)
+ value
+ end
+
+ def canonicalize(value)
+ self.class.canonicalize(value)
+ end
+
# A wrapper around our munging that makes sure we raise useful exceptions.
def munge(value)
begin
- ret = unsafe_munge(value)
+ ret = unsafe_munge(canonicalize(value))
rescue Puppet::Error => detail
Puppet.debug "Reraising %s" % detail
raise
diff --git a/lib/puppet/parser/ast/boolean_operator.rb b/lib/puppet/parser/ast/boolean_operator.rb
index 160e0e69e..89725d73b 100644
--- a/lib/puppet/parser/ast/boolean_operator.rb
+++ b/lib/puppet/parser/ast/boolean_operator.rb
@@ -20,14 +20,14 @@ class Puppet::Parser::AST
# return result
# lazy evaluate right operand
case @operator
- when "and";
+ when "and"
if Puppet::Parser::Scope.true?(lval)
rval = @rval.safeevaluate(scope)
Puppet::Parser::Scope.true?(rval)
else # false and false == false
false
end
- when "or";
+ when "or"
if Puppet::Parser::Scope.true?(lval)
true
else
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index a7f81b4e7..a6763c419 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -102,18 +102,24 @@ class Puppet::Parser::Collector
raise Puppet::DevError, "Cannot collect resources for a nil host" unless @scope.host
host = Puppet::Rails::Host.find_by_name(@scope.host)
- query = {:include => {:param_values => :param_name}}
-
search = "(exported=? AND restype=?)"
values = [true, @type]
search += " AND (%s)" % @equery if @equery
- # this is a small performance optimisation
- # the tag mechanism involves 3 more joins, which are
- # needed only if we query on tags.
- if search =~ /puppet_tags/
- query[:include][:puppet_tags] = :resource_tags
+ # note:
+ # we're not eagerly including any relations here because
+ # it can creates so much objects we'll throw out later.
+ # We used to eagerly include param_names/values but the way
+ # the search filter is built ruined those efforts and we
+ # were eagerly loading only the searched parameter and not
+ # the other ones.
+ query = {}
+ case search
+ when /puppet_tags/
+ query = {:joins => {:resource_tags => :puppet_tag}}
+ when /param_name/
+ query = {:joins => {:param_values => :param_name}}
end
# We're going to collect objects from rails, but we don't want any
@@ -139,7 +145,7 @@ class Puppet::Parser::Collector
# and such, we'll need to vary the conditions, but this works with no
# attributes, anyway.
time = Puppet::Util.thinmark do
- Puppet::Rails::Resource.find(:all, @type, true, query).each do |obj|
+ Puppet::Rails::Resource.find(:all, query).each do |obj|
if resource = exported_resource(obj)
count += 1
resources << resource
diff --git a/lib/puppet/parser/functions/generate.rb b/lib/puppet/parser/functions/generate.rb
index 1be9016ed..18fe883b4 100644
--- a/lib/puppet/parser/functions/generate.rb
+++ b/lib/puppet/parser/functions/generate.rb
@@ -1,7 +1,7 @@
# Runs an external command and returns the results
Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
- :doc => "Calls an external command and returns the results of the
- command. Any arguments are passed to the external command as
+ :doc => "Calls an external command on the Puppet master and returns
+ the results of the command. Any arguments are passed to the external command as
arguments. If the generator does not exit with return code of 0,
the generator is considered to have failed and a parse error is
thrown. Generators can only have file separators, alphanumerics, dashes,
diff --git a/lib/puppet/parser/functions/require.rb b/lib/puppet/parser/functions/require.rb
index 3a2032d7f..d72169af5 100644
--- a/lib/puppet/parser/functions/require.rb
+++ b/lib/puppet/parser/functions/require.rb
@@ -27,7 +27,10 @@ Note that this function only works with clients 0.25 and later, and it will
fail if used with earlier clients.
") do |vals|
- send(:function_include, vals)
+ # Verify that the 'include' function is loaded
+ method = Puppet::Parser::Functions.function(:include)
+
+ send(method, vals)
if resource.metaparam_compatibility_mode?
warning "The 'require' function is only compatible with clients at 0.25 and above; including class but not adding dependency"
else
diff --git a/lib/puppet/parser/functions/versioncmp.rb b/lib/puppet/parser/functions/versioncmp.rb
index bdf539127..9435655a7 100644
--- a/lib/puppet/parser/functions/versioncmp.rb
+++ b/lib/puppet/parser/functions/versioncmp.rb
@@ -18,7 +18,7 @@ This functions returns a number::
Example::
if versioncmp('2.6-1', '2.4.5') > 0 {
- notify('2.6-1 is > than 2.4.5')
+ notice('2.6-1 is > than 2.4.5')
}
") do |args|
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index b8aaf2715..651ed4224 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -139,6 +139,12 @@ class Puppet::Parser::Resource
if params = options[:params]
options.delete(:params)
params.each do |param|
+ # Don't set the same parameter twice
+ if @params[param.name]
+ self.fail Puppet::ParseError, "Duplicate parameter '%s' for on %s" %
+ [param.name, self.to_s]
+ end
+
set_parameter(param)
end
end
diff --git a/lib/puppet/provider/package/dpkg.rb b/lib/puppet/provider/package/dpkg.rb
index a4c398282..d6ec56ad4 100755
--- a/lib/puppet/provider/package/dpkg.rb
+++ b/lib/puppet/provider/package/dpkg.rb
@@ -83,7 +83,7 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
def latest
output = dpkg_deb "--show", @resource[:source]
matches = /^(\S+)\t(\S+)$/.match(output).captures
- unless matches[0].match(@resource[:name])
+ unless matches[0].match( Regexp.escape(@resource[:name]) )
warning "source doesn't contain named package, but %s" % matches[0]
end
matches[1]
diff --git a/lib/puppet/provider/package/portage.rb b/lib/puppet/provider/package/portage.rb
index e92058040..bd03aad2e 100644
--- a/lib/puppet/provider/package/portage.rb
+++ b/lib/puppet/provider/package/portage.rb
@@ -1,7 +1,6 @@
require 'puppet/provider/package'
Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Package do
- include Puppet::Util::Execution
desc "Provides packaging support for Gentoo's portage system."
has_feature :versionable
@@ -13,33 +12,32 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
defaultfor :operatingsystem => :gentoo
def self.instances
- result_format = /(\S+) (\S+) \[(?:([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\([^\)]+\))?(?:\[([^\]]+)\])?[ ]*)*\] \[(?:(?:\{M\})?(?:\([~*]+\))?([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\(([^\)]+)\))?(?:![mf])*(?:\[([^\]]+)\])?)?\] ([\S]*) (.*)/
- result_fields = [:category, :name, :ensure, :ensure_overlay, :version_available, :slot, :overlay, :vendor, :description]
+ result_format = /(\S+) (\S+) \[(\S+)\] \[(\S+)\] (\S+) (.*)/
+ result_fields = [:category, :name, :ensure, :version_available, :vendor, :description]
- version_format = "<version>{!last} {}"
- search_format = "<category> <name> [<installedversions:SPLITVERSIONS>] [<bestversion:SPLITVERSIONS>] <homepage> <description>"
+ version_format = "{last}<version>{}"
+ search_format = "<category> <name> [<installedversions:LASTVERSION>] [<bestversion:LASTVERSION>] <homepage> <description>\n"
begin
if !FileUtils.uptodate?("/var/cache/eix", %w(/usr/bin/eix /usr/portage/metadata/timestamp))
update_eix
end
+
search_output = nil
- withenv :SPLITVERSIONS => version_format do
- search_output = eix "--nocolor", "--pure-packages", "--installed", "--format", search_format
+ Puppet::Util::Execution.withenv :LASTVERSION => version_format do
+ search_output = eix "--nocolor", "--pure-packages", "--stable", "--installed", "--format", search_format
end
packages = []
search_output.each do |search_result|
- match = result_format.match( search_result )
+ match = result_format.match(search_result)
if match
package = {}
- result_fields.zip(match.captures) { |field, value|
+ result_fields.zip(match.captures) do |field, value|
package[field] = value unless !value or value.empty?
- }
+ end
package[:provider] = :portage
- package[:ensure] = package[:ensure].split.last
-
packages << new(package)
end
end
@@ -74,36 +72,35 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
end
def query
- result_format = /(\S+) (\S+) \[(?:([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\([^\)]+\))?(?:\[([^\]]+)\])?[ ]*)*\] \[(?:(?:\{M\})?(?:\([~*]+\))?([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\(([^\)]+)\))?(?:![mf])*(?:\[([^\]]+)\])?)?\] ([\S]*) (.*)/
- result_fields = [:category, :name, :ensure, :ensure_overlay, :version_available, :slot, :overlay, :vendor, :description]
+ result_format = /(\S+) (\S+) \[(\S*)\] \[(\S+)\] (\S+) (.*)/
+ result_fields = [:category, :name, :ensure, :version_available, :vendor, :description]
+
+ version_format = "{last}<version>{}"
+ search_format = "<category> <name> [<installedversions:LASTVERSION>] [<bestversion:LASTVERSION>] <homepage> <description>\n"
search_field = package_name.count('/') > 0 ? "--category-name" : "--name"
search_value = package_name
- version_format = "<version>{!last} {}"
- search_format = "<category> <name> [<installedversions:FORMAT_PVERSION>] [<bestversion:FORMAT_PVERSION>] <homepage> <description>"
-
begin
if !FileUtils.uptodate?("/var/cache/eix", %w(/usr/bin/eix /usr/portage/metadata/timestamp))
update_eix
end
+
search_output = nil
- withenv :SPLITVERSIONS => version_format do
- search_output = eix "--nocolor", "--pure-packages", "--format", search_format, "--exact", search_field, search_value
+ Puppet::Util::Execution.withenv :LASTVERSION => version_format do
+ search_output = eix "--nocolor", "--pure-packages", "--stable", "--format", search_format, "--exact", search_field, search_value
end
packages = []
search_output.each do |search_result|
- match = result_format.match( search_result )
+ match = result_format.match(search_result)
- if( match )
+ if match
package = {}
- result_fields.zip( match.captures ) { |field, value| package[field] = value unless !value or value.empty? }
- if package[:ensure]
- package[:ensure] = package[:ensure].split.last
- else
- package[:ensure] = :absent
+ result_fields.zip(match.captures) do |field, value|
+ package[field] = value unless !value or value.empty?
end
+ package[:ensure] = package[:ensure] ? package[:ensure] : :absent
packages << package
end
end
@@ -126,4 +123,3 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
return self.query[:version_available]
end
end
-
diff --git a/lib/puppet/provider/package/rug.rb b/lib/puppet/provider/package/rug.rb
index b68ec30c5..ca27cbbd3 100644
--- a/lib/puppet/provider/package/rug.rb
+++ b/lib/puppet/provider/package/rug.rb
@@ -36,7 +36,7 @@ Puppet::Type.type(:package).provide :rug, :parent => :rpm do
#rug can only get a list of *all* available packages?
output = rug "list-updates"
- if output =~ /#{@resource[:name]}\s*\|\s*([0-9\.\-]+)/
+ if output =~ /#{Regexp.escape @resource[:name]}\s*\|\s*([0-9\.\-]+)/
return $1
else
# rug didn't find updates, pretend the current
diff --git a/lib/puppet/provider/package/up2date.rb b/lib/puppet/provider/package/up2date.rb
index d8a12652f..284bbaf42 100644
--- a/lib/puppet/provider/package/up2date.rb
+++ b/lib/puppet/provider/package/up2date.rb
@@ -25,7 +25,7 @@ Puppet::Type.type(:package).provide :up2date, :parent => :rpm, :source => :rpm d
#up2date can only get a list of *all* available packages?
output = up2date "--showall"
- if output =~ /^#{@resource[:name]}-(\d+.*)\.\w+/
+ if output =~ /^#{Regexp.escape @resource[:name]}-(\d+.*)\.\w+/
return $1
else
# up2date didn't find updates, pretend the current
diff --git a/lib/puppet/provider/package/urpmi.rb b/lib/puppet/provider/package/urpmi.rb
index a95835284..a79e96227 100644
--- a/lib/puppet/provider/package/urpmi.rb
+++ b/lib/puppet/provider/package/urpmi.rb
@@ -43,7 +43,7 @@ Puppet::Type.type(:package).provide :urpmi, :parent => :rpm, :source => :rpm do
def latest
output = urpmq "-S", @resource[:name]
- if output =~ /^#{@resource[:name]}\s+:\s+.*\(\s+(\S+)\s+\)/
+ if output =~ /^#{Regexp.escape @resource[:name]}\s+:\s+.*\(\s+(\S+)\s+\)/
return $1
else
# urpmi didn't find updates, pretend the current
diff --git a/lib/puppet/provider/service/daemontools.rb b/lib/puppet/provider/service/daemontools.rb
index 2c6c6dbc7..3749f9c2c 100644
--- a/lib/puppet/provider/service/daemontools.rb
+++ b/lib/puppet/provider/service/daemontools.rb
@@ -45,7 +45,7 @@ Puppet::Type.type(:service).provide :daemontools, :parent => :base do
attr_writer :defpath
# Determine the daemon path.
- def defpath
+ def defpath(dummy_argument=:work_arround_for_ruby_GC_bug)
unless defined?(@defpath) and @defpath
["/var/lib/service", "/etc"].each do |path|
if FileTest.exist?(path)
diff --git a/lib/puppet/provider/service/debian.rb b/lib/puppet/provider/service/debian.rb
index 7ddbd288b..51fb7a22b 100755
--- a/lib/puppet/provider/service/debian.rb
+++ b/lib/puppet/provider/service/debian.rb
@@ -29,7 +29,7 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
def enabled?
# TODO: Replace system() call when Puppet::Util.execute gives us a way
# to determine exit status. http://projects.reductivelabs.com/issues/2538
- system("/usr/sbin/invoke-rc.d", "--query", @resource[:name], "start")
+ system("/usr/sbin/invoke-rc.d", "--quiet", "--query", @resource[:name], "start")
# 104 is the exit status when you query start an enabled service.
# 106 is the exit status when the policy layer supplies a fallback action
diff --git a/lib/puppet/provider/service/runit.rb b/lib/puppet/provider/service/runit.rb
index b313fc79c..b8b444e34 100644
--- a/lib/puppet/provider/service/runit.rb
+++ b/lib/puppet/provider/service/runit.rb
@@ -38,7 +38,7 @@ Puppet::Type.type(:service).provide :runit, :parent => :daemontools do
class << self
# this is necessary to autodetect a valid resource
# default path, since there is no standard for such directory.
- def defpath
+ def defpath(dummy_argument=:work_arround_for_ruby_GC_bug)
unless defined?(@defpath) and @defpath
["/etc/sv", "/var/lib/service"].each do |path|
if FileTest.exist?(path)
diff --git a/lib/puppet/provider/ssh_authorized_key/parsed.rb b/lib/puppet/provider/ssh_authorized_key/parsed.rb
index 69eec9fde..b435c513c 100644
--- a/lib/puppet/provider/ssh_authorized_key/parsed.rb
+++ b/lib/puppet/provider/ssh_authorized_key/parsed.rb
@@ -14,8 +14,9 @@ Puppet::Type.type(:ssh_authorized_key).provide(:parsed,
:fields => %w{options type key name},
:optional => %w{options},
:rts => /^\s+/,
- :match => /^(?:(.+) )?(ssh-dss|ssh-rsa) ([^ ]+)(?: (.+))?$/,
+ :match => /^(?:(.+) )?(ssh-dss|ssh-rsa) ([^ ]+) ?(.*)$/,
:post_parse => proc { |h|
+ h[:name] = "" if h[:name] == :absent
h[:options] ||= [:absent]
h[:options] = Puppet::Type::Ssh_authorized_key::ProviderParsed.parse_options(h[:options]) if h[:options].is_a? String
},
diff --git a/lib/puppet/provider/zone/solaris.rb b/lib/puppet/provider/zone/solaris.rb
index 778b9e0a1..b047f6984 100644
--- a/lib/puppet/provider/zone/solaris.rb
+++ b/lib/puppet/provider/zone/solaris.rb
@@ -64,7 +64,7 @@ Puppet::Type.type(:zone).provide(:solaris) do
@property_hash.clear
end
- def install
+ def install(dummy_argument=:work_arround_for_ruby_GC_bug)
if @resource[:install_args]
zoneadm :install, @resource[:install_args].split(" ")
else
@@ -156,11 +156,16 @@ Puppet::Type.type(:zone).provide(:solaris) do
def start
# Check the sysidcfg stuff
if cfg = @resource[:sysidcfg]
- path = File.join(@resource[:path], "root", "etc", "sysidcfg")
+ zoneetc = File.join(@resource[:path], "root", "etc")
+ sysidcfg = File.join(zoneetc, "sysidcfg")
- unless File.exists?(path)
+ # if the zone root isn't present "ready" the zone
+ # which makes zoneadmd mount the zone root
+ zoneadm :ready unless File.directory?(zoneetc)
+
+ unless File.exists?(sysidcfg)
begin
- File.open(path, "w", 0600) do |f|
+ File.open(sysidcfg, "w", 0600) do |f|
f.puts cfg
end
rescue => detail
@@ -193,6 +198,10 @@ Puppet::Type.type(:zone).provide(:solaris) do
main
end
+ def ready
+ zoneadm :ready
+ end
+
def stop
zoneadm :halt
end
diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb
index c941d8f3d..34ca58c5a 100644
--- a/lib/puppet/rails.rb
+++ b/lib/puppet/rails.rb
@@ -22,6 +22,10 @@ module Puppet::Rails
ActiveRecord::Base.logger.level = Logger::DEBUG
end
+ if (::ActiveRecord::VERSION::MAJOR == 2 and ::ActiveRecord::VERSION::MINOR <= 1)
+ ActiveRecord::Base.allow_concurrency = true
+ end
+
ActiveRecord::Base.verify_active_connections!
begin
diff --git a/lib/puppet/rails/resource.rb b/lib/puppet/rails/resource.rb
index 12d321143..984bdc05a 100644
--- a/lib/puppet/rails/resource.rb
+++ b/lib/puppet/rails/resource.rb
@@ -199,7 +199,7 @@ class Puppet::Rails::Resource < ActiveRecord::Base
result
end
- def ref
+ def ref(dummy_argument=:work_arround_for_ruby_GC_bug)
"%s[%s]" % [self[:restype].split("::").collect { |s| s.capitalize }.join("::"), self.title.to_s]
end
diff --git a/lib/puppet/resource/catalog.rb b/lib/puppet/resource/catalog.rb
index 5bf9a8368..f21c820a0 100644
--- a/lib/puppet/resource/catalog.rb
+++ b/lib/puppet/resource/catalog.rb
@@ -78,7 +78,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
@resource_table[ref] = resource
# If the name and title differ, set up an alias
- #self.alias(resource, resource.name) if resource.respond_to?(:name) and resource.respond_to?(:title) and resource.name != resource.title
+
if resource.respond_to?(:name) and resource.respond_to?(:title) and resource.name != resource.title
self.alias(resource, resource.name) if resource.isomorphic?
end
@@ -430,12 +430,12 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
# the class.
edge = Puppet::Relationship.from_pson(edge) if edge.is_a?(Hash)
unless source = result.resource(edge.source)
- raise ArgumentError, "Could not convert from pson: Could not find relationship source '%s'" % source
+ raise ArgumentError, "Could not convert from pson: Could not find relationship source #{edge.source.inspect}"
end
edge.source = source
unless target = result.resource(edge.target)
- raise ArgumentError, "Could not convert from pson: Could not find relationship target '%s'" % target
+ raise ArgumentError, "Could not convert from pson: Could not find relationship target #{edge.target.inspect}"
end
edge.target = target
diff --git a/lib/puppet/resource/reference.rb b/lib/puppet/resource/reference.rb
index c205f1038..dce4449de 100644
--- a/lib/puppet/resource/reference.rb
+++ b/lib/puppet/resource/reference.rb
@@ -20,24 +20,12 @@ class Puppet::Resource::Reference
end
def initialize(argtype, argtitle = nil)
- if argtitle.nil?
- if argtype.is_a?(Puppet::Type)
- self.title = argtype.title
- self.type = argtype.class.name
- else
- self.title = argtype
- if self.title == argtype
- raise ArgumentError, "No title provided and title '%s' is not a valid resource reference" % argtype.inspect
- end
- end
- else
- # This will set @type if it looks like a resource reference.
- self.title = argtitle
-
- # Don't override whatever was done by setting the title.
- self.type ||= argtype
- end
-
+ self.type,self.title =
+ if (argtitle || argtype) =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ]
+ elsif argtitle then [ argtype, argtitle ]
+ elsif argtype.is_a?(Puppet::Type) then [ argtype.class.name, argtype.title ]
+ else raise ArgumentError, "No title provided and #{argtype.inspect} is not a valid resource reference"
+ end
@builtin_type = nil
end
@@ -47,15 +35,11 @@ class Puppet::Resource::Reference
return nil
end
- # If the title has square brackets, treat it like a reference and
- # set things appropriately; else, just set it.
def title=(value)
- if value =~ /^([^\[\]]+)\[(.+)\]$/
- self.type = $1
- @title = $2
- else
- @title = value
+ if @type and klass = Puppet::Type.type(@type.to_s.downcase)
+ value = klass.canonicalize_ref(value)
end
+ @title = value
end
# Canonize the type so we know it's always consistent.
diff --git a/lib/puppet/ssl/certificate_revocation_list.rb b/lib/puppet/ssl/certificate_revocation_list.rb
index f3c1a348a..c725bde48 100644
--- a/lib/puppet/ssl/certificate_revocation_list.rb
+++ b/lib/puppet/ssl/certificate_revocation_list.rb
@@ -46,8 +46,6 @@ class Puppet::SSL::CertificateRevocationList < Puppet::SSL::Base
# The name doesn't actually matter; there's only one CRL.
# We just need the name so our Indirector stuff all works more easily.
def initialize(fakename)
- raise Puppet::Error, "Cannot manage the CRL when :cacrl is set to false" if [false, "false"].include?(Puppet[:cacrl])
-
@name = "crl"
end
diff --git a/lib/puppet/ssl/host.rb b/lib/puppet/ssl/host.rb
index d7993e70e..98061c5e2 100644
--- a/lib/puppet/ssl/host.rb
+++ b/lib/puppet/ssl/host.rb
@@ -235,12 +235,11 @@ class Puppet::SSL::Host
# Attempt to retrieve a cert, if we don't already have one.
def wait_for_cert(time)
- return if certificate
begin
+ return if certificate
generate
-
return if certificate
- rescue StandardError => detail
+ rescue Exception => detail
Puppet.err "Could not request certificate: %s" % detail.to_s
if time < 1
puts "Exiting; failed to retrieve certificate and watiforcert is disabled"
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index b0bcdb612..f6bcbc1f7 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -134,7 +134,7 @@ class Puppet::SSLCertificates::CA
# List certificates waiting to be signed. This returns a list of hostnames, not actual
# files -- the names can be converted to full paths with host2csrfile.
- def list
+ def list(dummy_argument=:work_arround_for_ruby_GC_bug)
return Dir.entries(Puppet[:csrdir]).find_all { |file|
file =~ /\.pem$/
}.collect { |file|
@@ -144,7 +144,7 @@ class Puppet::SSLCertificates::CA
# List signed certificates. This returns a list of hostnames, not actual
# files -- the names can be converted to full paths with host2csrfile.
- def list_signed
+ def list_signed(dummy_argument=:work_arround_for_ruby_GC_bug)
return Dir.entries(Puppet[:signeddir]).find_all { |file|
file =~ /\.pem$/
}.collect { |file|
@@ -194,9 +194,6 @@ class Puppet::SSLCertificates::CA
# Revoke the certificate with serial number SERIAL issued by this
# CA. The REASON must be one of the OpenSSL::OCSP::REVOKED_* reasons
def revoke(serial, reason = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE)
- if @config[:cacrl] == 'false'
- raise Puppet::Error, "Revocation requires a CRL, but ca_crl is set to 'false'"
- end
time = Time.now
revoked = OpenSSL::X509::Revoked.new
revoked.serial = serial
@@ -344,8 +341,6 @@ class Puppet::SSLCertificates::CA
@crl = OpenSSL::X509::CRL.new(
File.read(@config[:cacrl])
)
- elsif @config[:cacrl] == 'false'
- @crl = nil
else
# Create new CRL
@crl = OpenSSL::X509::CRL.new
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index d04856d39..e132b7238 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -2,6 +2,7 @@
# and performs them
require 'puppet'
+require 'puppet/util/tagging'
module Puppet
class Transaction
@@ -18,6 +19,7 @@ class Transaction
attr_reader :events
include Puppet::Util
+ include Puppet::Util::Tagging
# Add some additional times for reporting
def addtimes(hash)
@@ -353,6 +355,7 @@ class Transaction
made = [made] unless made.is_a?(Array)
made.uniq.find_all do |res|
begin
+ res.tag(*resource.tags)
@catalog.add_resource(res) do |r|
r.finish
make_parent_child_relationship(resource, [r])
@@ -601,26 +604,26 @@ class Transaction
# The tags we should be checking.
def tags
unless defined? @tags
- tags = Puppet[:tags]
- if tags.nil? or tags == ""
- @tags = []
- else
- @tags = tags.split(/\s*,\s*/)
- end
+ self.tags = Puppet[:tags]
end
- @tags
+ super
end
- def tags=(tags)
- tags = [tags] unless tags.is_a?(Array)
- @tags = tags
+ def handle_qualified_tags( qualified )
+ # The default behavior of Puppet::Util::Tagging is
+ # to split qualified tags into parts. That would cause
+ # qualified tags to match too broadly here.
+ return
end
# Is this resource tagged appropriately?
def missing_tags?(resource)
- return false if self.ignore_tags? or tags.empty?
- return true unless resource.tagged?(tags)
+ not appropriately_tagged?(resource)
+ end
+
+ def appropriately_tagged?(resource)
+ self.ignore_tags? or tags.empty? or resource.tagged?(*tags)
end
# Are there any edges that target this resource?
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index ee87c2680..2f7b57afc 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -210,8 +210,8 @@ class Type
end
# Find the namevar
- def self.namevar
- unless defined? @namevar
+ def self.namevar_parameter
+ @namevar_parameter ||= (
params = @parameters.find_all { |param|
param.isnamevar? or param.name == :name
}
@@ -219,12 +219,19 @@ class Type
if params.length > 1
raise Puppet::DevError, "Found multiple namevars for %s" % self.name
elsif params.length == 1
- @namevar = params[0].name
+ params.first
else
raise Puppet::DevError, "No namevar for %s" % self.name
end
- end
- @namevar
+ )
+ end
+
+ def self.namevar
+ @namevar ||= namevar_parameter.name
+ end
+
+ def self.canonicalize_ref(s)
+ namevar_parameter.canonicalize(s)
end
# Create a new parameter. Requires a block and a name, stores it in the
diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb
index 1269f3872..1cdd56184 100755
--- a/lib/puppet/type/cron.rb
+++ b/lib/puppet/type/cron.rb
@@ -312,7 +312,7 @@ Puppet::Type.newtype(:cron) do
the crontab, e.g., ``PATH=/bin:/usr/bin:/usr/sbin``."
validate do |value|
- unless value =~ /^\s*(\w+)\s*=\s*(.+)\s*$/ or value == :absent or value == "absent"
+ unless value =~ /^\s*(\w+)\s*=\s*(.*)\s*$/ or value == :absent or value == "absent"
raise ArgumentError, "Invalid environment setting %s" %
value.inspect
end
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 34dc4454e..a4666a95f 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -46,6 +46,12 @@ module Puppet
unmunge do |value|
File.join( Puppet::FileCollection.collection.path(value[:index]), value[:name] )
end
+
+ to_canonicalize do |s|
+ # Get rid of any duplicate slashes, and remove any trailing slashes unless
+ # the title is just a slash, in which case leave it.
+ s.gsub(/\/+/, "/").sub(/(.)\/$/,'\1')
+ end
end
newparam(:backup) do
@@ -120,10 +126,10 @@ module Puppet
munge do |value|
newval = super(value)
case newval
- when :true, :inf: true
- when :false: false
- when :remote: :remote
- when Integer, Fixnum, Bignum:
+ when :true, :inf; true
+ when :false; false
+ when :remote; :remote
+ when Integer, Fixnum, Bignum
self.warning "Setting recursion depth with the recurse parameter is now deprecated, please use recurselimit"
# recurse == 0 means no recursion
@@ -131,7 +137,7 @@ module Puppet
resource[:recurselimit] = value
true
- when /^\d+$/:
+ when /^\d+$/
self.warning "Setting recursion depth with the recurse parameter is now deprecated, please use recurselimit"
value = Integer(value)
@@ -154,8 +160,8 @@ module Puppet
munge do |value|
newval = super(value)
case newval
- when Integer, Fixnum, Bignum: value
- when /^\d+$/: Integer(value)
+ when Integer, Fixnum, Bignum; value
+ when /^\d+$/; Integer(value)
else
raise ArgumentError, "Invalid recurselimit value %s" % value.inspect
end
@@ -399,11 +405,7 @@ module Puppet
super
- # Get rid of any duplicate slashes, and remove any trailing slashes.
- @title = @title.gsub(/\/+/, "/")
-
- @title.sub!(/\/$/, "") unless @title == "/"
-
+ @title = self.class.canonicalize_ref(@title)
@stat = nil
end
@@ -494,26 +496,18 @@ module Puppet
# not likely to have many actual conflicts, which is good, because
# this is a pretty inefficient implementation.
def remove_less_specific_files(files)
- # We sort the paths so we can short-circuit some tests.
- mypath = self[:path]
- other_paths = catalog.vertices.find_all do |r|
- r.is_a?(self.class) and r[:path][0..(mypath.length - 1)] == mypath
- end.collect { |r| r[:path] }.sort { |a, b| a.length <=> b.length } - [self[:path]]
+ mypath = self[:path].split(File::Separator)
+ other_paths = catalog.vertices.
+ select { |r| r.is_a?(self.class) and r[:path] != self[:path] }.
+ collect { |r| r[:path].split(File::Separator) }.
+ select { |p| p[0,mypath.length] == mypath }
return files if other_paths.empty?
- remove = []
- files.each do |file|
- path = file[:path]
- other_paths.each do |p|
- if path[0..(p.length - 1)] == p
- remove << file
- break
- end
- end
- end
-
- files - remove
+ files.reject { |file|
+ path = file[:path].split(File::Separator)
+ other_paths.any? { |p| path[0,p.length] == p }
+ }
end
# A simple method for determining whether we should be recursing.
diff --git a/lib/puppet/type/file/content.rb b/lib/puppet/type/file/content.rb
index ff71a55ce..36e6c4172 100755
--- a/lib/puppet/type/file/content.rb
+++ b/lib/puppet/type/file/content.rb
@@ -96,7 +96,7 @@ module Puppet
return true if ! @resource.replace?
if self.should
- return super
+ result = super
elsif source = resource.parameter(:source)
fail "Got a remote source with no checksum" unless source.checksum
result = (is == source.checksum)
@@ -114,14 +114,14 @@ module Puppet
def retrieve
return :absent unless stat = @resource.stat
-
+ ftype = stat.ftype
# Don't even try to manage the content on directories or links
- return nil if stat.ftype == "directory"
+ return nil if ["directory","link"].include? ftype
begin
- return "{#{checksum_type}}" + send(checksum_type.to_s + "_file", resource[:path]).to_s
+ "{#{checksum_type}}" + send(checksum_type.to_s + "_file", resource[:path]).to_s
rescue => detail
- raise Puppet::Error, "Could not read %s: %s" % [@resource.title, detail]
+ raise Puppet::Error, "Could not read #{ftype} #{@resource.title}: #{detail}"
end
end
diff --git a/lib/puppet/type/file/mode.rb b/lib/puppet/type/file/mode.rb
index fd9c27ae6..83034cbd9 100755
--- a/lib/puppet/type/file/mode.rb
+++ b/lib/puppet/type/file/mode.rb
@@ -5,7 +5,24 @@ module Puppet
Puppet::Type.type(:file).newproperty(:mode) do
require 'etc'
desc "Mode the file should be. Currently relatively limited:
- you must specify the exact mode the file should be."
+ you must specify the exact mode the file should be.
+
+ Note that when you set the mode of a directory, Puppet always
+ sets the search/traverse (1) bit anywhere the read (4) bit is set.
+ This is almost always what you want: read allows you to list the
+ entries in a directory, and search/traverse allows you to access
+ (read/write/execute) those entries.) Because of this feature, you
+ can recursively make a directory and all of the files in it
+ world-readable by setting e.g.::
+
+ file { '/some/dir':
+ mode => 644,
+ recurse => true,
+ }
+
+ In this case all of the files underneath ``/some/dir`` will have
+ mode 644, and all of the directories will have mode 755."
+
@event = :file_changed
# Our modes are octal, so make sure they print correctly. Other
diff --git a/lib/puppet/type/file/owner.rb b/lib/puppet/type/file/owner.rb
index 1dff59cb3..e5ca06a86 100755
--- a/lib/puppet/type/file/owner.rb
+++ b/lib/puppet/type/file/owner.rb
@@ -28,10 +28,7 @@ module Puppet
end
def insync?(current)
- unless Puppet::Util::SUIDManager.uid == 0
- warning "Cannot manage ownership unless running as root"
- return true
- end
+ return true unless should
@should.each do |value|
if value =~ /^\d+$/
@@ -44,6 +41,12 @@ module Puppet
return true if uid == current
end
+
+ unless Puppet::Util::SUIDManager.uid == 0
+ warnonce "Cannot manage ownership unless running as root"
+ return true
+ end
+
return false
end
diff --git a/lib/puppet/type/k5login.rb b/lib/puppet/type/k5login.rb
index 20c03241f..5526fda21 100644
--- a/lib/puppet/type/k5login.rb
+++ b/lib/puppet/type/k5login.rb
@@ -56,7 +56,7 @@ Puppet::Type.newtype(:k5login) do
end
# Return the principals
- def principals
+ def principals(dummy_argument=:work_arround_for_ruby_GC_bug)
if File.exists?(@resource[:name])
File.readlines(@resource[:name]).collect { |line| line.chomp }
else
diff --git a/lib/puppet/type/maillist.rb b/lib/puppet/type/maillist.rb
index e2430aa13..4ab9be252 100755
--- a/lib/puppet/type/maillist.rb
+++ b/lib/puppet/type/maillist.rb
@@ -42,13 +42,10 @@ module Puppet
should = :absent
end
atype = Puppet::Type.type(:mailalias)
- return provider.aliases.collect do |name, recipient|
- if atype[name]
- nil
- else
- malias = Puppet::Type.type(:mailalias).new(:name => name, :recipient => recipient, :ensure => should)
- end
- end.compact
+
+ provider.aliases.
+ reject { |name,recipient| catalog.resource(:mailalias, name) }.
+ collect { |name,recipient| atype.new(:name => name, :recipient => recipient, :ensure => should) }
end
end
end
diff --git a/lib/puppet/type/resources.rb b/lib/puppet/type/resources.rb
index 87bde972b..e1de55711 100644
--- a/lib/puppet/type/resources.rb
+++ b/lib/puppet/type/resources.rb
@@ -99,18 +99,18 @@ Puppet::Type.newtype(:resources) do
def generate
return [] unless self.purge?
resource_type.instances.
- reject { |r| managed? }.
- reject { |r| catalog.resources.include? r.ref }.
- select { |r| check(r) }.
- select { |r| able_to_ensure_absent?(r) }.
- each { |resource|
- @parameters.each do |name, param|
- resource[name] = param.value if param.metaparam?
- end
-
- # Mark that we're purging, so transactions can handle relationships
- # correctly
- resource.purging
+ reject { |r| catalog.resources.include? r.ref }.
+ select { |r| check(r) }.
+ select { |r| r.class.validproperty?(:ensure) }.
+ select { |r| able_to_ensure_absent?(r) }.
+ each { |resource|
+ @parameters.each do |name, param|
+ resource[name] = param.value if param.metaparam?
+ end
+
+ # Mark that we're purging, so transactions can handle relationships
+ # correctly
+ resource.purging
}
end
diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb
index f45171d90..b5ccb3fb1 100755
--- a/lib/puppet/type/tidy.rb
+++ b/lib/puppet/type/tidy.rb
@@ -247,8 +247,15 @@ Puppet::Type.newtype(:tidy) do
def generate
return [] unless stat(self[:path])
- if self[:recurse]
- files = Puppet::FileServing::Fileset.new(self[:path], :recurse => self[:recurse]).files.collect do |f|
+ case self[:recurse]
+ when Integer, Fixnum, Bignum, /^\d+$/
+ parameter = { :recurse => true, :recurselimit => self[:recurse] }
+ when true, :true, :inf
+ parameter = { :recurse => true }
+ end
+
+ if parameter
+ files = Puppet::FileServing::Fileset.new(self[:path], parameter).files.collect do |f|
f == "." ? self[:path] : File.join(self[:path], f)
end
else
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 6f83c7ac5..21573d1da 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -55,10 +55,11 @@ module Util
end
unless Puppet::Util::SUIDManager.uid == user
begin
+ Puppet::Util::SUIDManager.initgroups(user)
Puppet::Util::SUIDManager.uid = user
Puppet::Util::SUIDManager.euid = user
- rescue
- $stderr.puts "could not change to user %s" % user
+ rescue => detail
+ $stderr.puts "Could not change to user %s: %s" % [user, detail]
exit(74)
end
end
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb
index 25c4677fb..4cdad700c 100644
--- a/lib/puppet/util/log.rb
+++ b/lib/puppet/util/log.rb
@@ -282,9 +282,9 @@ class Puppet::Util::Log
def colorize(level, str)
case Puppet[:color]
- when false; str
- when true, :ansi, "ansi"; console_color(level, str)
+ when true, :ansi, "ansi", :yes, "yes"; console_color(level, str)
when :html, "html"; html_color(level, str)
+ else str
end
end
diff --git a/lib/puppet/util/methodhelper.rb b/lib/puppet/util/methodhelper.rb
index 32fca1877..ecc9d537f 100644
--- a/lib/puppet/util/methodhelper.rb
+++ b/lib/puppet/util/methodhelper.rb
@@ -12,11 +12,10 @@ module Puppet::Util::MethodHelper
def set_options(options)
options.each do |param,value|
method = param.to_s + "="
- begin
+ if respond_to? method
self.send(method, value)
- rescue NoMethodError
- raise ArgumentError, "Invalid parameter %s to object class %s" %
- [param,self.class.to_s]
+ else
+ raise ArgumentError, "Invalid parameter #{param} to object class #{self.class}"
end
end
end
diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb
index e69de29bb..6e438bc73 100644
--- a/lib/puppet/util/monkey_patches.rb
+++ b/lib/puppet/util/monkey_patches.rb
@@ -0,0 +1,8 @@
+module RDoc
+ def self.caller(skip=nil)
+ in_gem_wrapper = false
+ Kernel.caller.reject { |call|
+ in_gem_wrapper ||= call =~ /#{Regexp.escape $0}:\d+:in `load'/
+ }
+ end
+end
diff --git a/lib/puppet/util/rdoc/parser.rb b/lib/puppet/util/rdoc/parser.rb
index 3f04fbf52..4d0ac484f 100644
--- a/lib/puppet/util/rdoc/parser.rb
+++ b/lib/puppet/util/rdoc/parser.rb
@@ -200,9 +200,20 @@ class Parser
if stmt.is_a?(Puppet::Parser::AST::Resource) and !stmt.type.nil?
begin
- ref = resource_stmt_to_ref(stmt)
- Puppet.debug "rdoc: found resource: %s[%s]" % [ref.type, ref.title]
- container.add_resource(ref)
+ type = stmt.type.split("::").collect { |s| s.capitalize }.join("::")
+ title = stmt.title.is_a?(Puppet::Parser::AST::ASTArray) ? stmt.title.to_s.gsub(/\[(.*)\]/,'\1') : stmt.title.to_s
+ Puppet.debug "rdoc: found resource: %s[%s]" % [type,title]
+
+ param = []
+ stmt.params.children.each do |p|
+ res = {}
+ res["name"] = p.param
+ res["value"] = "#{p.value.to_s}" unless p.value.nil?
+
+ param << res
+ end
+
+ container.add_resource(PuppetResource.new(type, title, stmt.doc, param))
rescue => detail
raise Puppet::ParseError, "impossible to parse resource in #{stmt.file} at line #{stmt.line}: #{detail}"
end
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
index bdf44152b..3eff03996 100644
--- a/lib/puppet/util/selinux.rb
+++ b/lib/puppet/util/selinux.rb
@@ -13,6 +13,8 @@ rescue LoadError
# Nothing
end
+require 'pathname'
+
module Puppet::Util::SELinux
def selinux_support?
@@ -91,7 +93,7 @@ module Puppet::Util::SELinux
# I believe that the OS should always provide at least a fall-through context
# though on any well-running system.
def set_selinux_context(file, value, component = false)
- unless selinux_support?
+ unless selinux_support? && selinux_label_support?(file)
return nil
end
@@ -185,9 +187,19 @@ module Puppet::Util::SELinux
return mntpoint
end
+ def realpath(path)
+ path, rest = Pathname.new(path), []
+ path, rest = path.dirname, [path.basename] + rest while ! path.exist?
+ File.join( path.realpath, *rest )
+ end
+
+ def parent_directory(path)
+ Pathname.new(path).dirname.to_s
+ end
+
# Internal helper function to return which type of filesystem a
# given file path resides on
- def find_fs(file)
+ def find_fs(path)
unless mnts = read_mounts()
return nil
end
@@ -198,13 +210,12 @@ module Puppet::Util::SELinux
# Just in case: return something if you're down to "/" or ""
# Remove the last slash and everything after it,
# and repeat with that as the file for the next loop through.
- ary = file.split('/')
- while not ary.empty? do
- path = ary.join('/')
+ path = realpath(path)
+ while not path.empty? do
if mnts.has_key?(path)
return mnts[path]
end
- ary.pop
+ path = parent_directory(path)
end
return mnts['/']
end
diff --git a/lib/puppet/util/subclass_loader.rb b/lib/puppet/util/subclass_loader.rb
index 8776e855c..b71ec7293 100644
--- a/lib/puppet/util/subclass_loader.rb
+++ b/lib/puppet/util/subclass_loader.rb
@@ -72,7 +72,7 @@ module Puppet::Util::SubclassLoader
end
# Retrieve or calculate a name.
- def name
+ def name(dummy_argument=:work_arround_for_ruby_GC_bug)
unless defined? @name
@name = self.to_s.sub(/.+::/, '').intern
end
diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb
index c5df0d198..a0a9178bb 100644
--- a/lib/puppet/util/suidmanager.rb
+++ b/lib/puppet/util/suidmanager.rb
@@ -7,7 +7,7 @@ module Puppet::Util::SUIDManager
extend Forwardable
to_delegate_to_process = [ :euid=, :euid, :egid=, :egid,
- :uid=, :uid, :gid=, :gid ]
+ :uid=, :uid, :gid=, :gid, :groups=, :groups ]
to_delegate_to_process.each do |method|
def_delegator Process, method
@@ -26,13 +26,16 @@ module Puppet::Util::SUIDManager
# We set both because some programs like to drop privs, i.e. bash.
old_uid, old_gid = self.uid, self.gid
old_euid, old_egid = self.euid, self.egid
+ old_groups = self.groups
begin
self.egid = convert_xid :gid, new_gid if new_gid
+ self.initgroups(convert_xid(:uid, new_uid)) if new_uid
self.euid = convert_xid :uid, new_uid if new_uid
yield
ensure
self.euid, self.egid = old_euid, old_egid
+ self.groups = old_groups
end
end
module_function :asuser
@@ -49,6 +52,13 @@ module Puppet::Util::SUIDManager
end
module_function :convert_xid
+ # Initialize supplementary groups
+ def initgroups(user)
+ require 'etc'
+ Process.initgroups(Etc.getpwuid(user).name, Process.gid)
+ end
+
+ module_function :initgroups
def run_and_capture(command, new_uid=nil, new_gid=nil)
output = Puppet::Util.execute(command, :failonfail => false, :uid => new_uid, :gid => new_gid)
diff --git a/lib/puppet/util/tagging.rb b/lib/puppet/util/tagging.rb
index f421d18d8..9ee90799f 100644
--- a/lib/puppet/util/tagging.rb
+++ b/lib/puppet/util/tagging.rb
@@ -16,13 +16,12 @@ module Puppet::Util::Tagging
@tags << tag unless @tags.include?(tag)
end
- # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
- qualified.collect { |name| x = name.split("::") }.flatten.each { |tag| @tags << tag unless @tags.include?(tag) }
+ handle_qualified_tags( qualified )
end
# Are we tagged with the provided tag?
- def tagged?(tag)
- defined?(@tags) and @tags.include?(tag.to_s)
+ def tagged?(*tags)
+ not ( self.tags & tags.flatten.collect { |t| t.to_s } ).empty?
end
# Return a copy of the tag list, so someone can't ask for our tags
@@ -32,8 +31,27 @@ module Puppet::Util::Tagging
@tags.dup
end
+ def tags=(tags)
+ @tags = []
+
+ return if tags.nil? or tags == ""
+
+ if tags.is_a?(String)
+ tags = tags.strip.split(/\s*,\s*/)
+ end
+
+ tags.each do |t|
+ tag(t)
+ end
+ end
+
private
+ def handle_qualified_tags( qualified )
+ # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
+ qualified.collect { |name| x = name.split("::") }.flatten.each { |tag| @tags << tag unless @tags.include?(tag) }
+ end
+
def valid_tag?(tag)
tag =~ /^\w[-\w:.]*$/
end
diff --git a/spec/integration/defaults.rb b/spec/integration/defaults.rb
index 0e9a03fcb..590be1310 100755
--- a/spec/integration/defaults.rb
+++ b/spec/integration/defaults.rb
@@ -29,6 +29,17 @@ describe "Puppet defaults" do
end
end
+ describe "when setting the :catalog_format" do
+ it "should log a deprecation notice" do
+ Puppet.expects(:warning)
+ Puppet.settings[:catalog_format] = 'marshal'
+ end
+ it "should copy the value to :preferred_serialization_format" do
+ Puppet.settings[:catalog_format] = 'marshal'
+ Puppet.settings[:preferred_serialization_format].should == 'marshal'
+ end
+ end
+
it "should have a clientyamldir setting" do
Puppet.settings[:clientyamldir].should_not be_nil
end
diff --git a/spec/integration/type/file.rb b/spec/integration/type/file.rb
index 40f9244f1..fe6e2ddc6 100755
--- a/spec/integration/type/file.rb
+++ b/spec/integration/type/file.rb
@@ -223,7 +223,7 @@ describe Puppet::Type.type(:file) do
end
it "should not recursively manage files managed by a more specific explicit file" do
- dir = tmpfile("file_source_integration_source")
+ dir = tmpfile("recursion_vs_explicit_1")
subdir = File.join(dir, "subdir")
file = File.join(subdir, "file")
@@ -242,6 +242,25 @@ describe Puppet::Type.type(:file) do
(File.stat(file).mode & 007777).should == 0644
end
+
+ it "should recursively manage files even if there is an explicit file whose name is a prefix of the managed file" do
+ dir = tmpfile("recursion_vs_explicit_2")
+
+ managed = File.join(dir, "file")
+ generated = File.join(dir, "file_with_a_name_starting_with_the_word_file")
+
+ FileUtils.mkdir_p(dir)
+ File.open(managed, "w") { |f| f.puts "" }
+ File.open(generated, "w") { |f| f.puts "" }
+
+ @catalog = Puppet::Resource::Catalog.new
+ @catalog.add_resource Puppet::Type::File.new(:name => dir, :recurse => true, :backup => false, :mode => "755")
+ @catalog.add_resource Puppet::Type::File.new(:name => managed, :recurse => true, :backup => false, :mode => "644")
+
+ @catalog.apply
+
+ (File.stat(generated).mode & 007777).should == 0755
+ end
end
describe "when generating resources" do
diff --git a/spec/unit/application/puppetd.rb b/spec/unit/application/puppetd.rb
index 380608506..04c6daf32 100755
--- a/spec/unit/application/puppetd.rb
+++ b/spec/unit/application/puppetd.rb
@@ -40,7 +40,7 @@ describe "puppetd" do
describe "in preinit" do
before :each do
- @pupetd.stubs(:trap)
+ @puppetd.stubs(:trap)
end
it "should catch INT" do
diff --git a/spec/unit/application/puppetdoc.rb b/spec/unit/application/puppetdoc.rb
index b9173752f..cb60581a4 100755
--- a/spec/unit/application/puppetdoc.rb
+++ b/spec/unit/application/puppetdoc.rb
@@ -290,16 +290,16 @@ describe "puppetdoc" do
@puppetdoc.manifest = false
Puppet.stubs(:info)
Puppet.stubs(:[]).with(:trace).returns(false)
- Puppet.stubs(:[]).with(:modulepath).returns('modules')
- Puppet.stubs(:[]).with(:manifestdir).returns('manifests')
+ @env = stub 'env'
+ Puppet::Node::Environment.stubs(:new).returns(@env)
+ @env.stubs(:modulepath).returns(['modules'])
+ @env.stubs(:manifestdir).returns(['manifests'])
@puppetdoc.options.stubs(:[]).with(:all).returns(false)
@puppetdoc.options.stubs(:[]).with(:outputdir).returns('doc')
Puppet.settings.stubs(:[]=).with(:document_all, false)
Puppet.settings.stubs(:setdefaults)
Puppet::Util::RDoc.stubs(:rdoc)
@puppetdoc.stubs(:exit)
- File.stubs(:expand_path).with('modules').returns('modules')
- File.stubs(:expand_path).with('manifests').returns('manifests')
@old = ARGV.dup
ARGV.clear
end
@@ -331,6 +331,15 @@ describe "puppetdoc" do
Puppet::Util::RDoc.expects(:manifestdoc)
@puppetdoc.rdoc
end
+
+ it "should get modulepath and manifestdir values from the environment" do
+ @env.expects(:modulepath).returns(['envmodules1','envmodules2'])
+ @env.expects(:manifestdir).returns(['envmanifests1','envmanifests2'])
+
+ Puppet::Util::RDoc.expects(:rdoc).with('doc', ['envmodules1','envmodules2','envmanifests1','envmanifests2'])
+
+ @puppetdoc.rdoc
+ end
end
describe "in the other modes" do
diff --git a/spec/unit/configurer.rb b/spec/unit/configurer.rb
index 0490967ba..cd5102546 100755
--- a/spec/unit/configurer.rb
+++ b/spec/unit/configurer.rb
@@ -183,6 +183,12 @@ describe Puppet::Configurer, "when converting the catalog" do
@agent.convert_catalog(@oldcatalog, 10).should equal(@catalog)
end
+ it "should finalize the catalog" do
+ @catalog.expects(:finalize)
+
+ @agent.convert_catalog(@oldcatalog, 10)
+ end
+
it "should record the passed retrieval time with the RAL catalog" do
@catalog.expects(:retrieval_duration=).with 10
diff --git a/spec/unit/configurer/fact_handler.rb b/spec/unit/configurer/fact_handler.rb
index 0c4af9554..ec60c6dcd 100755
--- a/spec/unit/configurer/fact_handler.rb
+++ b/spec/unit/configurer/fact_handler.rb
@@ -102,7 +102,7 @@ describe Puppet::Configurer::FactHandler do
@facthandler.expects(:find_facts).returns facts
- @facthandler.facts_for_uploading.should == {:facts_format => :yaml, :facts => text}
+ @facthandler.facts_for_uploading.should == {:facts_format => :b64_zlib_yaml, :facts => text}
end
it "should properly accept facts containing a '+'" do
@@ -112,12 +112,12 @@ describe Puppet::Configurer::FactHandler do
@facthandler.expects(:find_facts).returns facts
- @facthandler.facts_for_uploading.should == {:facts_format => :yaml, :facts => text}
+ @facthandler.facts_for_uploading.should == {:facts_format => :b64_zlib_yaml, :facts => text}
end
it "should hard-code yaml as the serialization" do
facts = stub 'facts'
- facts.expects(:render).with(:yaml).returns "my text"
+ facts.expects(:render).with(:b64_zlib_yaml).returns "my text"
text = CGI.escape("my text")
@facthandler.expects(:find_facts).returns facts
diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb
index f6acfad39..4621a0c82 100755
--- a/spec/unit/file_serving/configuration.rb
+++ b/spec/unit/file_serving/configuration.rb
@@ -104,17 +104,31 @@ describe Puppet::FileServing::Configuration do
it "should allow all access to modules and plugins if no fileserver.conf exists" do
FileTest.expects(:exists?).returns false # the file doesn't exist
- modules = stub 'modules'
+ modules = stub 'modules', :empty? => true
Puppet::FileServing::Mount::Modules.stubs(:new).returns(modules)
modules.expects(:allow).with('*')
- plugins = stub 'plugins'
+ plugins = stub 'plugins', :empty? => true
Puppet::FileServing::Mount::Plugins.stubs(:new).returns(plugins)
plugins.expects(:allow).with('*')
Puppet::FileServing::Configuration.create
end
+ it "should not allow access from all to modules and plugins if the fileserver.conf provided some rules" do
+ FileTest.expects(:exists?).returns false # the file doesn't exist
+
+ modules = stub 'modules', :empty? => false
+ Puppet::FileServing::Mount::Modules.stubs(:new).returns(modules)
+ modules.expects(:allow).with('*').never
+
+ plugins = stub 'plugins', :empty? => false
+ Puppet::FileServing::Mount::Plugins.stubs(:new).returns(plugins)
+ plugins.expects(:allow).with('*').never
+
+ Puppet::FileServing::Configuration.create
+ end
+
it "should add modules and plugins mounts even if they are not returned by the parser" do
@parser.expects(:parse).returns("one" => mock("mount"))
FileTest.expects(:exists?).returns true # the file doesn't exist
diff --git a/spec/unit/file_serving/metadata.rb b/spec/unit/file_serving/metadata.rb
index de0c4570c..c27efd6bb 100755
--- a/spec/unit/file_serving/metadata.rb
+++ b/spec/unit/file_serving/metadata.rb
@@ -20,6 +20,84 @@ describe Puppet::FileServing::Metadata do
it "should have a method that triggers attribute collection" do
Puppet::FileServing::Metadata.new("/foo/bar").should respond_to(:collect)
end
+
+ it "should support pson serialization" do
+ Puppet::FileServing::Metadata.new("/foo/bar").should respond_to(:to_pson)
+ end
+
+ it "should support to_pson_data_hash" do
+ Puppet::FileServing::Metadata.new("/foo/bar").should respond_to(:to_pson_data_hash)
+ end
+
+ it "should support pson deserialization" do
+ Puppet::FileServing::Metadata.should respond_to(:from_pson)
+ end
+
+ describe "when serializing" do
+ before do
+ @metadata = Puppet::FileServing::Metadata.new("/foo/bar")
+ end
+ 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
+
+ it "the data should include the path, relative_path, links, owner, group, mode, checksum, type, and destination" 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
+ end
+
+ it "should pass the relative_path in the hash verbatum" do
+ @metadata.to_pson_data_hash['data']['relative_path'] == @metadata.relative_path
+ end
+
+ it "should pass the links in the hash verbatum" do
+ @metadata.to_pson_data_hash['data']['links'] == @metadata.links
+ end
+
+ it "should pass the path owner in the hash verbatum" do
+ @metadata.to_pson_data_hash['data']['owner'] == @metadata.owner
+ end
+
+ it "should pass the group in the hash verbatum" do
+ @metadata.to_pson_data_hash['data']['group'] == @metadata.group
+ end
+
+ it "should pass the mode in the hash verbatum" do
+ @metadata.to_pson_data_hash['data']['mode'] == @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
+ end
+
+ it "should pass the destination verbatum" do
+ @metadata.to_pson_data_hash['data']['destination'] == @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
+ 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
+ end
+
+ end
end
describe Puppet::FileServing::Metadata, " when finding the file to use for setting attributes" do
diff --git a/spec/unit/indirector/catalog/active_record.rb b/spec/unit/indirector/catalog/active_record.rb
index 463552f55..8678dd6b3 100755
--- a/spec/unit/indirector/catalog/active_record.rb
+++ b/spec/unit/indirector/catalog/active_record.rb
@@ -76,9 +76,12 @@ describe "Puppet::Resource::Catalog::ActiveRecord" do
describe "when saving an instance" do
before do
- @host = stub 'host', :name => "foo", :save => nil, :merge_resources => nil, :last_compile= => nil
+ @host = stub 'host', :name => "foo", :save => nil, :merge_resources => nil, :last_compile= => nil, :ip= => nil, :environment= => nil
@host.stubs(:railsmark).yields
+ @node = stub_everything 'node', :parameters => {}
+ Puppet::Node.stubs(:find).returns(@node)
+
Puppet::Rails::Host.stubs(:find_by_name).returns @host
@catalog = Puppet::Resource::Catalog.new("foo")
@request = stub 'request', :key => "foo", :instance => @catalog
@@ -105,6 +108,22 @@ describe "Puppet::Resource::Catalog::ActiveRecord" do
@terminus.save(@request)
end
+ it "should set host ip if we could find a matching node" do
+ @node.stubs(:parameters).returns({"ipaddress" => "192.168.0.1"})
+
+ @host.expects(:ip=).with '192.168.0.1'
+
+ @terminus.save(@request)
+ end
+
+ it "should set host environment if we could find a matching node" do
+ @node.stubs(:environment).returns("myenv")
+
+ @host.expects(:environment=).with 'myenv'
+
+ @terminus.save(@request)
+ end
+
it "should set the last compile time on the host" do
now = Time.now
Time.expects(:now).returns now
diff --git a/spec/unit/network/authstore.rb b/spec/unit/network/authstore.rb
index 55b2c7bbc..4087b28ed 100644
--- a/spec/unit/network/authstore.rb
+++ b/spec/unit/network/authstore.rb
@@ -4,6 +4,36 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/network/authconfig'
+describe Puppet::Network::AuthStore do
+ describe "when checking if the acl has some entries" do
+ before :each do
+ @authstore = Puppet::Network::AuthStore.new
+ end
+
+ it "should be empty if no ACE have been entered" do
+ @authstore.should be_empty
+ end
+
+ it "should not be empty if it is a global allow" do
+ @authstore.allow('*')
+
+ @authstore.should_not be_empty
+ end
+
+ it "should not be empty if at least one allow has been entered" do
+ @authstore.allow('1.1.1.*')
+
+ @authstore.should_not be_empty
+ end
+
+ it "should not be empty if at least one deny has been entered" do
+ @authstore.deny('1.1.1.*')
+
+ @authstore.should_not be_empty
+ end
+ end
+end
+
describe Puppet::Network::AuthStore::Declaration do
['100.101.99.98','100.100.100.100','1.2.3.4','11.22.33.44'].each { |ip|
diff --git a/spec/unit/network/format_handler.rb b/spec/unit/network/format_handler.rb
index 8a79a58b3..110effe09 100755
--- a/spec/unit/network/format_handler.rb
+++ b/spec/unit/network/format_handler.rb
@@ -49,15 +49,35 @@ describe Puppet::Network::FormatHandler do
FormatTester.supported_formats.should == [:four, :two, :three, :one]
end
- it "should always put the preferred serialization format first if it is supported" do
- one = stub 'supported', :supported? => true, :name => :one, :weight => 1
- two = stub 'supported', :supported? => true, :name => :two, :weight => 6
- Puppet.settings.expects(:value).with(:preferred_serialization_format).returns :one
- Puppet::Network::FormatHandler.stubs(:formats).returns [:one, :two]
- Puppet::Network::FormatHandler.stubs(:format).with(:one).returns one
- Puppet::Network::FormatHandler.stubs(:format).with(:two).returns two
- FormatTester.supported_formats.should == [:one, :two]
+ describe "with a preferred serialization format setting" do
+ before do
+ one = stub 'supported', :supported? => true, :name => :one, :weight => 1
+ two = stub 'supported', :supported? => true, :name => :two, :weight => 6
+ Puppet::Network::FormatHandler.stubs(:formats).returns [:one, :two]
+ Puppet::Network::FormatHandler.stubs(:format).with(:one).returns one
+ Puppet::Network::FormatHandler.stubs(:format).with(:two).returns two
+ end
+ describe "that is supported" do
+ before do
+ Puppet.settings.expects(:value).with(:preferred_serialization_format).returns :one
+ end
+ it "should return the preferred serialization format first" do
+ FormatTester.supported_formats.should == [:one, :two]
+ end
+ end
+ describe "that is not supported" do
+ before do
+ Puppet.settings.expects(:value).with(:preferred_serialization_format).returns :unsupported
+ end
+ it "should still return the default format first" do
+ FormatTester.supported_formats.should == [:two, :one]
+ end
+ it "should log a warning" do
+ Puppet.expects(:warning)
+ FormatTester.supported_formats
+ end
+ end
end
it "should return the first format as the default format" do
diff --git a/spec/unit/network/formats.rb b/spec/unit/network/formats.rb
index de2e0afe3..b1ef9ec53 100755
--- a/spec/unit/network/formats.rb
+++ b/spec/unit/network/formats.rb
@@ -90,6 +90,91 @@ describe "Puppet Network Format" do
end
end
+ describe "base64 compressed yaml" do
+ before do
+ @yaml = Puppet::Network::FormatHandler.format(:b64_zlib_yaml)
+ end
+
+ it "should have its mime type set to text/b64_zlib_yaml" do
+ @yaml.mime.should == "text/b64_zlib_yaml"
+ end
+
+ it "should render by calling 'to_yaml' on the instance" do
+ instance = mock 'instance'
+ instance.expects(:to_yaml).returns "foo"
+ @yaml.render(instance)
+ end
+
+ it "should fixup generated yaml on render" do
+ instance = mock 'instance', :to_yaml => "foo"
+
+ @yaml.expects(:fixup).with("foo").returns "bar"
+
+ @yaml.render(instance)
+ end
+
+ it "should encode generated yaml on render" do
+ instance = mock 'instance', :to_yaml => "foo"
+
+ @yaml.expects(:encode).with("foo").returns "bar"
+
+ @yaml.render(instance).should == "bar"
+ end
+
+ it "should render multiple instances by calling 'to_yaml' on the array" do
+ instances = [mock('instance')]
+ instances.expects(:to_yaml).returns "foo"
+ @yaml.render_multiple(instances)
+ end
+
+ it "should fixup generated yaml on render" do
+ instances = [mock('instance')]
+ instances.stubs(:to_yaml).returns "foo"
+
+ @yaml.expects(:fixup).with("foo").returns "bar"
+
+ @yaml.render(instances)
+ end
+
+ it "should encode generated yaml on render" do
+ instances = [mock('instance')]
+ instances.stubs(:to_yaml).returns "foo"
+
+ @yaml.expects(:encode).with("foo").returns "bar"
+
+ @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"
+ 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"
+ end
+
+ it "should decode by base64 decoding, uncompressing and Yaml loading" do
+ Base64.expects(:decode64).with("zorg").returns "foo"
+ Zlib::Inflate.expects(:inflate).with("foo").returns "baz"
+ YAML.expects(:load).with("baz").returns "bar"
+ @yaml.decode("zorg").should == "bar"
+ 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"
+ end
+
+ it "should fixup incorrect yaml to correct" do
+ @yaml.fixup("&id004 !ruby/object:Puppet::Relationship ?").should == "? &id004 !ruby/object:Puppet::Relationship"
+ end
+ end
+
it "should include a marshal format" do
Puppet::Network::FormatHandler.format(:marshal).should_not be_nil
end
diff --git a/spec/unit/network/http/webrick.rb b/spec/unit/network/http/webrick.rb
index 1b76341ba..fca2e075e 100755
--- a/spec/unit/network/http/webrick.rb
+++ b/spec/unit/network/http/webrick.rb
@@ -15,7 +15,7 @@ end
describe Puppet::Network::HTTP::WEBrick, "when turning on listening" do
before do
- @mock_webrick = stub('webrick', :[] => {})
+ @mock_webrick = stub('webrick', :[] => {}, :listeners => [])
[:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)}
WEBrick::HTTPServer.stubs(:new).returns(@mock_webrick)
@server = Puppet::Network::HTTP::WEBrick.new
@@ -162,7 +162,7 @@ end
describe Puppet::Network::HTTP::WEBrick, "when turning off listening" do
before do
- @mock_webrick = stub('webrick', :[] => {})
+ @mock_webrick = stub('webrick', :[] => {}, :listeners => [])
[:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)}
WEBrick::HTTPServer.stubs(:new).returns(@mock_webrick)
@server = Puppet::Network::HTTP::WEBrick.new
diff --git a/spec/unit/network/rights.rb b/spec/unit/network/rights.rb
index 244fa18c8..7f00891ac 100755
--- a/spec/unit/network/rights.rb
+++ b/spec/unit/network/rights.rb
@@ -391,7 +391,7 @@ describe Puppet::Network::Rights do
end
it "should match as a regex" do
- @acl.match?("this shoud work.rb").should_not be_nil
+ @acl.match?("this should work.rb").should_not be_nil
end
it "should return nil if no match" do
diff --git a/spec/unit/node/environment.rb b/spec/unit/node/environment.rb
index a16b3d6e1..9b0d5eefa 100755
--- a/spec/unit/node/environment.rb
+++ b/spec/unit/node/environment.rb
@@ -22,6 +22,10 @@ describe Puppet::Node::Environment do
Puppet::Node::Environment.attr_ttl(:modules).should == Integer(Puppet[:filetimeout])
end
+ it "should use the filetimeout for the ttl for the manifestdir" do
+ Puppet::Node::Environment.attr_ttl(:manifestdir).should == Integer(Puppet[:filetimeout])
+ end
+
it "should use the default environment if no name is provided while initializing an environment" do
Puppet.settings.expects(:value).with(:environment).returns("one")
Puppet::Node::Environment.new().name.should == :one
@@ -39,45 +43,57 @@ describe Puppet::Node::Environment do
Puppet::Node::Environment.new(:one).to_s.should == "one"
end
- it "should consider its module path to be the environment-specific modulepath setting" do
- FileTest.stubs(:directory?).returns true
- env = Puppet::Node::Environment.new("testing")
- module_path = %w{/one /two}.join(File::PATH_SEPARATOR)
- env.expects(:[]).with(:modulepath).returns module_path
+ [:modulepath, :manifestdir].each do |setting|
+ it "should validate the #{setting} directories" do
+ path = %w{/one /two}.join(File::PATH_SEPARATOR)
+
+ env = Puppet::Node::Environment.new("testing")
+ env.stubs(:[]).with(setting).returns path
+
+ env.expects(:validate_dirs).with(%w{/one /two})
+
+ env.send(setting)
+ end
+
+ it "should return the validated dirs for #{setting}" do
+ path = %w{/one /two}.join(File::PATH_SEPARATOR)
- env.modulepath.should == %w{/one /two}
+ env = Puppet::Node::Environment.new("testing")
+ env.stubs(:[]).with(setting).returns path
+ env.stubs(:validate_dirs).returns %w{/one /two}
+
+ env.send(setting).should == %w{/one /two}
+ end
end
it "should prefix the value of the 'PUPPETLIB' environment variable to the module path if present" do
- FileTest.stubs(:directory?).returns true
Puppet::Util::Execution.withenv("PUPPETLIB" => %w{/l1 /l2}.join(File::PATH_SEPARATOR)) do
env = Puppet::Node::Environment.new("testing")
module_path = %w{/one /two}.join(File::PATH_SEPARATOR)
+ env.expects(:validate_dirs).with(%w{/l1 /l2 /one /two}).returns %w{/l1 /l2 /one /two}
env.expects(:[]).with(:modulepath).returns module_path
env.modulepath.should == %w{/l1 /l2 /one /two}
end
end
- it "should not return non-directories in the module path" do
- env = Puppet::Node::Environment.new("testing")
- module_path = %w{/one /two}.join(File::PATH_SEPARATOR)
- env.expects(:[]).with(:modulepath).returns module_path
+ describe "when validating modulepath or manifestdir directories" do
+ it "should not return non-directories" do
+ env = Puppet::Node::Environment.new("testing")
- FileTest.expects(:directory?).with("/one").returns true
- FileTest.expects(:directory?).with("/two").returns false
+ FileTest.expects(:directory?).with("/one").returns true
+ FileTest.expects(:directory?).with("/two").returns false
- env.modulepath.should == %w{/one}
- end
+ env.validate_dirs(%w{/one /two}).should == %w{/one}
+ end
- it "should use the current working directory to fully-qualify unqualified paths" do
- FileTest.stubs(:directory?).returns true
- env = Puppet::Node::Environment.new("testing")
- module_path = %w{/one two}.join(File::PATH_SEPARATOR)
- env.expects(:[]).with(:modulepath).returns module_path
+ it "should use the current working directory to fully-qualify unqualified paths" do
+ FileTest.stubs(:directory?).returns true
+ env = Puppet::Node::Environment.new("testing")
- two = File.join(Dir.getwd, "two")
- env.modulepath.should == ["/one", two]
+ two = File.join(Dir.getwd, "two")
+ env.validate_dirs(%w{/one two}).should == ["/one", two]
+ end
end
describe "when modeling a specific environment" do
diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/collector.rb
index 926033c68..7f88bf754 100755
--- a/spec/unit/parser/collector.rb
+++ b/spec/unit/parser/collector.rb
@@ -498,35 +498,46 @@ describe Puppet::Parser::Collector, "when building its ActiveRecord query for co
Puppet::Rails::Host.expects(:find_by_name).with(@scope.host).returns(@host)
Puppet::Rails::Resource.stubs(:find).with { |*arguments|
- options = arguments[3]
+ options = arguments[1]
options[:conditions][0] =~ /^host_id != \?/ and options[:conditions][1] == 5
}.returns([@resource])
@collector.evaluate.should == [@resource]
end
- it "should return parameter names, parameter values when querying ActiveRecord" do
+ it "should join with parameter names, parameter values when querying ActiveRecord" do
+ @collector.equery = "param_names.name = title"
Puppet::Rails::Resource.stubs(:find).with { |*arguments|
- options = arguments[3]
- options[:include] == {:param_values => :param_name}
+ options = arguments[1]
+ options[:joins] == {:param_values => :param_name}
}.returns([@resource])
@collector.evaluate.should == [@resource]
end
- it "should return tags when querying ActiveRecord with a tag exported query" do
+ it "should join with tag tables when querying ActiveRecord with a tag exported query" do
@collector.equery = "puppet_tags.name = test"
Puppet::Rails::Resource.stubs(:find).with { |*arguments|
- options = arguments[3]
- options[:include] == {:param_values => :param_name, :puppet_tags => :resource_tags}
+ options = arguments[1]
+ options[:joins] == {:resource_tags => :puppet_tag}
}.returns([@resource])
@collector.evaluate.should == [@resource]
end
+ it "should not join parameters when querying ActiveRecord with a tag exported query" do
+ @collector.equery = "puppet_tags.name = test"
+ Puppet::Rails::Resource.stubs(:find).with { |*arguments|
+ options = arguments[1]
+ options[:joins] == {:param_values => :param_name}
+ }.returns([@resource])
+
+ @collector.evaluate.should be_false
+ end
+
it "should only search for exported resources with the matching type" do
Puppet::Rails::Resource.stubs(:find).with { |*arguments|
- options = arguments[3]
+ options = arguments[1]
options[:conditions][0].include?("(exported=? AND restype=?)") and options[:conditions][1] == true and options[:conditions][2] == "Mytype"
}.returns([@resource])
@@ -536,7 +547,7 @@ describe Puppet::Parser::Collector, "when building its ActiveRecord query for co
it "should include the export query if one is provided" do
@collector.equery = "test = true"
Puppet::Rails::Resource.stubs(:find).with { |*arguments|
- options = arguments[3]
+ options = arguments[1]
options[:conditions][0].include?("test = true")
}.returns([@resource])
diff --git a/spec/unit/parser/functions/require.rb b/spec/unit/parser/functions/require.rb
index 24c9ecc64..577a52a42 100755
--- a/spec/unit/parser/functions/require.rb
+++ b/spec/unit/parser/functions/require.rb
@@ -31,6 +31,12 @@ describe "the require function" do
@scope.function_require("myclass")
end
+ it "should verify the 'include' function is loaded" do
+ Puppet::Parser::Functions.expects(:function).with(:include).returns(:function_include)
+ @scope.stubs(:function_include)
+ @scope.function_require("myclass")
+ end
+
it "should include the class but not add a dependency if used on a client not at least version 0.25" do
@resource.expects(:metaparam_compatibility_mode?).returns true
@scope.expects(:warning)
diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb
index 0a67c4b54..3f08de958 100755
--- a/spec/unit/parser/resource.rb
+++ b/spec/unit/parser/resource.rb
@@ -25,7 +25,7 @@ describe Puppet::Parser::Resource do
params = args[:params] || {:one => "yay", :three => "rah"}
if args[:params] == :none
args.delete(:params)
- else
+ elsif not args[:params].is_a? Array
args[:params] = paramify(args[:source], params)
end
@@ -483,5 +483,18 @@ describe Puppet::Parser::Resource do
result = @parser_resource.to_resource
result[:fee].should == ["a", Puppet::Resource::Reference.new(:file, "/my/file1"), Puppet::Resource::Reference.new(:file, "/my/file2")]
end
+
+ it "should fail if the same param is declared twice" do
+ lambda do
+ @parser_resource = mkresource :source => @source, :params => [
+ Puppet::Parser::Resource::Param.new(
+ :name => :foo, :value => "bar", :source => @source
+ ),
+ Puppet::Parser::Resource::Param.new(
+ :name => :foo, :value => "baz", :source => @source
+ )
+ ]
+ end.should raise_error(Puppet::ParseError)
+ end
end
end
diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb
index e082136c5..064c51b20 100755
--- a/spec/unit/parser/resource/reference.rb
+++ b/spec/unit/parser/resource/reference.rb
@@ -40,10 +40,15 @@ describe Puppet::Parser::Resource::Reference do
ref.to_s.should == "File[/tmp/yay]"
end
- it "should canonize resource references" do
+ it "should canonize resource reference types" do
ref = @type.new(:type => "foo::bar", :title => "/tmp/yay")
ref.to_s.should == "Foo::Bar[/tmp/yay]"
end
+
+ it "should canonize resource reference values" do
+ ref = @type.new(:type => "file", :title => "/tmp/yay/")
+ ref.to_s.should == "File[/tmp/yay]"
+ end
end
describe Puppet::Parser::Resource::Reference, " when modeling defined types" do
diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb
index 0859eadb4..d7800e4b3 100755
--- a/spec/unit/parser/scope.rb
+++ b/spec/unit/parser/scope.rb
@@ -43,7 +43,7 @@ describe Puppet::Parser::Scope do
describe "and the variable is qualified" do
before do
@parser = Puppet::Parser::Parser.new()
- @compiler = Puppet::Parser::Compiler.new(stub("node", :name => "foonode"), @parser)
+ @compiler = Puppet::Parser::Compiler.new(stub("node", :name => "foonode", :classes => []), @parser)
@scope.compiler = @compiler
@scope.parser = @parser
end
diff --git a/spec/unit/property.rb b/spec/unit/property.rb
index 26a5765a2..03b848b15 100755
--- a/spec/unit/property.rb
+++ b/spec/unit/property.rb
@@ -101,6 +101,12 @@ describe Puppet::Property do
@property.should.must == [:one, :two]
end
+ it "should munge the canonicalization of the value" do
+ @property.class.to_canonicalize { |x| x.reverse }
+ @property.value = 'data'
+ @property.should.must == 'atad'
+ end
+
it "should return any set value" do
(@property.value = :one).should == :one
end
diff --git a/spec/unit/provider/package/dpkg.rb b/spec/unit/provider/package/dpkg.rb
index 08aaca875..0c5c9b527 100755
--- a/spec/unit/provider/package/dpkg.rb
+++ b/spec/unit/provider/package/dpkg.rb
@@ -149,6 +149,13 @@ describe provider do
@provider.expects(:warning)
@provider.latest
end
+
+ it "should cope with names containing ++" do
+ @resource = stub 'resource', :[] => "asdf++"
+ @provider = provider.new(@resource)
+ @provider.expects(:dpkg_deb).returns "asdf++\t1.0"
+ @provider.latest.should == "1.0"
+ end
end
it "should use 'dpkg -r' to uninstall" do
diff --git a/spec/unit/provider/service/debian.rb b/spec/unit/provider/service/debian.rb
index 87d627452..ea87c375d 100755
--- a/spec/unit/provider/service/debian.rb
+++ b/spec/unit/provider/service/debian.rb
@@ -60,7 +60,7 @@ describe provider_class do
describe "when checking whether it is enabled" do
it "should call Kernel.system() with the appropriate parameters" do
- @provider.expects(:system).with("/usr/sbin/invoke-rc.d", "--query", @resource[:name], "start").once
+ @provider.expects(:system).with("/usr/sbin/invoke-rc.d", "--quiet", "--query", @resource[:name], "start").once
@provider.enabled?
end
diff --git a/spec/unit/provider/ssh_authorized_key/parsed.rb b/spec/unit/provider/ssh_authorized_key/parsed.rb
index 13bd08bd8..49abc13ec 100755
--- a/spec/unit/provider/ssh_authorized_key/parsed.rb
+++ b/spec/unit/provider/ssh_authorized_key/parsed.rb
@@ -78,6 +78,12 @@ describe provider_class do
@provider.parse_options(optionstr).should == options
end
+
+ it "should use '' as name for entries that lack a comment" do
+ line = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAut8aOSxenjOqF527dlsdHWV4MNoAsX14l9M297+SQXaQ5Z3BedIxZaoQthkDALlV/25A1COELrg9J2MqJNQc8Xe9XQOIkBQWWinUlD/BXwoOTWEy8C8zSZPHZ3getMMNhGTBO+q/O+qiJx3y5cA4MTbw2zSxukfWC87qWwcZ64UUlegIM056vPsdZWFclS9hsROVEa57YUMrehQ1EGxT4Z5j6zIopufGFiAPjZigq/vqgcAqhAKP6yu4/gwO6S9tatBeEjZ8fafvj1pmvvIplZeMr96gHE7xS3pEEQqnB3nd4RY7AF6j9kFixnsytAUO7STPh/M3pLiVQBN89TvWPQ=="
+
+ @provider.parse(line)[0][:name].should == ""
+ end
end
describe provider_class do
diff --git a/spec/unit/rails.rb b/spec/unit/rails.rb
index 8ecd77a49..da6db1548 100755
--- a/spec/unit/rails.rb
+++ b/spec/unit/rails.rb
@@ -39,6 +39,7 @@ describe Puppet::Rails, "when initializing any connection" do
ActiveRecord::Base.stubs(:logger).returns(logger)
logger.expects(:level=).with(Logger::DEBUG)
+ ActiveRecord::Base.stubs(:allow_concurrency=)
ActiveRecord::Base.stubs(:verify_active_connections!)
ActiveRecord::Base.stubs(:establish_connection)
Puppet::Rails.stubs(:database_arguments)
@@ -46,6 +47,16 @@ describe Puppet::Rails, "when initializing any connection" do
Puppet::Rails.connect
end
+ describe "on ActiveRecord 2.1.x" do
+ confine "ActiveRecord 2.1.x" => (::ActiveRecord::VERSION::MAJOR == 2 and ::ActiveRecord::VERSION::MINOR <= 1)
+
+ it "should set ActiveRecord::Base.allow_concurrency" do
+ ActiveRecord::Base.expects(:allow_concurrency=).with(true)
+
+ Puppet::Rails.connect
+ end
+ end
+
it "should call ActiveRecord::Base.verify_active_connections!" do
ActiveRecord::Base.expects(:verify_active_connections!)
diff --git a/spec/unit/ssl/certificate_revocation_list.rb b/spec/unit/ssl/certificate_revocation_list.rb
index eb25268e6..3d15db78b 100755
--- a/spec/unit/ssl/certificate_revocation_list.rb
+++ b/spec/unit/ssl/certificate_revocation_list.rb
@@ -46,18 +46,6 @@ describe Puppet::SSL::CertificateRevocationList do
end
end
- describe "when initializing" do
- it "should fail if :cacrl is set to false" do
- Puppet.settings.expects(:value).with(:cacrl).returns false
- lambda { @class.new("crl") }.should raise_error(Puppet::Error)
- end
-
- it "should fail if :cacrl is set to the string 'false'" do
- Puppet.settings.expects(:value).with(:cacrl).returns "false"
- lambda { @class.new("crl") }.should raise_error(Puppet::Error)
- end
- end
-
describe "when generating the crl" do
before do
@real_crl = mock 'crl'
diff --git a/spec/unit/transaction.rb b/spec/unit/transaction.rb
index 7966c7a65..1b3562153 100755
--- a/spec/unit/transaction.rb
+++ b/spec/unit/transaction.rb
@@ -20,8 +20,8 @@ describe Puppet::Transaction do
describe "when generating resources" do
it "should finish all resources" do
- generator = stub 'generator', :depthfirst? => true
- resource = stub 'resource'
+ generator = stub 'generator', :depthfirst? => true, :tags => []
+ resource = stub 'resource', :tag => nil
@catalog = Puppet::Resource::Catalog.new
@transaction = Puppet::Transaction.new(@catalog)
@@ -36,8 +36,8 @@ describe Puppet::Transaction do
end
it "should skip generated resources that conflict with existing resources" do
- generator = mock 'generator'
- resource = stub 'resource'
+ generator = mock 'generator', :tags => []
+ resource = stub 'resource', :tag => nil
@catalog = Puppet::Resource::Catalog.new
@transaction = Puppet::Transaction.new(@catalog)
@@ -51,6 +51,21 @@ describe Puppet::Transaction do
@transaction.generate_additional_resources(generator, :generate).should be_empty
end
+
+ it "should copy all tags to the newly generated resources" do
+ child = stub 'child'
+ generator = stub 'resource', :tags => ["one", "two"]
+
+ @catalog = Puppet::Resource::Catalog.new
+ @transaction = Puppet::Transaction.new(@catalog)
+
+ generator.stubs(:generate).returns [child]
+ @catalog.stubs(:add_resource)
+
+ child.expects(:tag).with("one", "two")
+
+ @transaction.generate_additional_resources(generator, :generate)
+ end
end
describe "when skipping a resource" do
@@ -65,6 +80,16 @@ describe Puppet::Transaction do
@transaction.skip?(@resource).should be_true
end
+ it "should ask the resource if it's tagged with any of the tags" do
+ tags = ['one', 'two']
+ @transaction.stubs(:ignore_tags?).returns(false)
+ @transaction.stubs(:tags).returns(tags)
+
+ @resource.expects(:tagged?).with(*tags).returns(true)
+
+ @transaction.missing_tags?(@resource).should be_false
+ end
+
it "should skip not scheduled resources" do
@transaction.stubs(:scheduled?).returns(false)
@transaction.skip?(@resource).should be_true
@@ -108,4 +133,14 @@ describe Puppet::Transaction, " when determining tags" do
@transaction.tags = "one::two"
@transaction.tags.should == %w{one::two}
end
+
+ it "should accept a comma-delimited string" do
+ @transaction.tags = "one, two"
+ @transaction.tags.should == %w{one two}
+ end
+
+ it "should accept an empty string" do
+ @transaction.tags = ""
+ @transaction.tags.should == []
+ end
end
diff --git a/spec/unit/type/cron.rb b/spec/unit/type/cron.rb
new file mode 100755
index 000000000..6951077e0
--- /dev/null
+++ b/spec/unit/type/cron.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+describe Puppet::Type.type(:cron) do
+ before do
+ @cron = Puppet::Type.type(:cron).new( :name => "foo" )
+ end
+
+ it "it should accept an :environment that looks like a path" do
+ lambda do
+ @cron[:environment] = 'PATH=/bin:/usr/bin:/usr/sbin'
+ end.should_not raise_error
+ end
+
+ it "should not accept environment variables that do not contain '='" do
+ lambda do
+ @cron[:environment] = "INVALID"
+ end.should raise_error(Puppet::Error)
+ end
+
+ it "should accept empty environment variables that do not contain '='" do
+ lambda do
+ @cron[:environment] = "MAILTO="
+ end.should_not raise_error(Puppet::Error)
+ end
+
+ it "should accept 'absent'" do
+ lambda do
+ @cron[:environment] = 'absent'
+ end.should_not raise_error(Puppet::Error)
+ end
+end
diff --git a/spec/unit/type/file/content.rb b/spec/unit/type/file/content.rb
index 8bdb1f226..442de1309 100755
--- a/spec/unit/type/file/content.rb
+++ b/spec/unit/type/file/content.rb
@@ -119,6 +119,15 @@ describe content do
@content.retrieve.should be_nil
end
+ it "should not manage content on links" do
+ @content = content.new(:resource => @resource)
+
+ stat = mock 'stat', :ftype => "link"
+ @resource.expects(:stat).returns stat
+
+ @content.retrieve.should be_nil
+ end
+
it "should always return the checksum as a string" do
@content = content.new(:resource => @resource)
@content.stubs(:checksum_type).returns "mtime"
@@ -188,6 +197,26 @@ describe content do
@content.must be_insync("{md5}" + Digest::MD5.hexdigest("some content"))
end
+ describe "and Puppet[:show_diff] is set" do
+ before do
+ Puppet[:show_diff] = true
+ end
+
+ it "should display a diff if the current contents are different from the desired content" do
+ @content.should = "some content"
+ @content.expects(:string_file_diff).once
+
+ @content.insync?("other content")
+ end
+
+ it "should not display a diff if the sum for the current contents is the same as the sum for the desired content" do
+ @content.should = "some content"
+ @content.expects(:string_file_diff).never
+
+ @content.insync?("{md5}" + Digest::MD5.hexdigest("some content"))
+ end
+ end
+
describe "and the content is specified via a remote source" do
before do
@metadata = stub 'metadata'
diff --git a/spec/unit/type/file/owner.rb b/spec/unit/type/file/owner.rb
index 1ea01cbc7..62f7b0ae5 100755
--- a/spec/unit/type/file/owner.rb
+++ b/spec/unit/type/file/owner.rb
@@ -55,11 +55,13 @@ describe property do
describe "when determining if the file is in sync" do
describe "and not running as root" do
- it "should warn and return true" do
- @owner.should = 10
+ it "should warn once and return true" do
Puppet::Util::SUIDManager.expects(:uid).returns 1
- @owner.expects(:warning)
- @owner.must be_insync("whatever")
+
+ @owner.expects(:warnonce)
+
+ @owner.should = [10]
+ @owner.must be_insync(20)
end
end
@@ -67,6 +69,10 @@ describe property do
Puppet::Util::SUIDManager.stubs(:uid).returns 0
end
+ it "should be in sync if 'should' is not provided" do
+ @owner.must be_insync(10)
+ end
+
it "should directly compare the owner values if the desired owner is an integer" do
@owner.should = [10]
@owner.must be_insync(10)
diff --git a/spec/unit/type/maillist.rb b/spec/unit/type/maillist.rb
new file mode 100755
index 000000000..585336665
--- /dev/null
+++ b/spec/unit/type/maillist.rb
@@ -0,0 +1,42 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+maillist = Puppet::Type.type(:maillist)
+
+describe maillist do
+ before do
+ @provider_class = Puppet::Type.type(:maillist).provider(:mailman)
+
+ @provider = stub 'provider', :class => @provider_class, :clear => nil
+ @provider.stubs(:respond_to).with(:aliases).returns(true)
+
+ @provider_class.stubs(:new).returns(@provider)
+
+ Puppet::Type.type(:maillist).stubs(:defaultprovider).returns(@provider_class)
+
+ @maillist = Puppet::Type.type(:maillist).new( :name => 'test' )
+
+ @catalog = Puppet::Resource::Catalog.new
+ @maillist.catalog = @catalog
+ end
+
+ it "should generate aliases unless they already exist" do
+ # Mail List aliases are careful not to stomp on managed Mail Alias aliases
+
+ # test1 is an unmanaged alias from /etc/aliases
+ Puppet::Type.type(:mailalias).provider(:aliases).stubs(:target_object).returns( StringIO.new("test1: root\n") )
+
+ # test2 is a managed alias from the manifest
+ dupe = Puppet::Type.type(:mailalias).new( :name => 'test2' )
+ @catalog.add_resource dupe
+
+ @provider.stubs(:aliases).returns({"test1" => 'this will get included', "test2" => 'this will dropped', "test3" => 'this will get included'})
+
+ generated = @maillist.generate
+ generated.map{ |x| x.name }.sort.should == ['test1', 'test3']
+ generated.map{ |x| x.class }.should == [Puppet::Type::Mailalias, Puppet::Type::Mailalias]
+
+ end
+
+end
diff --git a/spec/unit/type/resources.rb b/spec/unit/type/resources.rb
index 147f21db4..480b6c00d 100644
--- a/spec/unit/type/resources.rb
+++ b/spec/unit/type/resources.rb
@@ -8,7 +8,7 @@ resources = Puppet::Type.type(:resources)
describe resources do
describe "when initializing" do
it "should fail if the specified resource type does not exist" do
- Puppet::Type.stubs(:type).with("Resources").returns resources
+ Puppet::Type.stubs(:type).with { |x| x.to_s.downcase == "resources"}.returns resources
Puppet::Type.expects(:type).with("nosuchtype").returns nil
lambda { resources.new :name => "nosuchtype" }.should raise_error(Puppet::Error)
end
@@ -21,4 +21,69 @@ describe resources do
resources.new(:name => "file").resource_type.should == Puppet::Type.type(:file)
end
end
+
+ describe "#generate" do
+ before do
+ @host1 = Puppet::Type.type(:host).new(:name => 'localhost', :ip => '127.0.0.1')
+ @catalog = Puppet::Resource::Catalog.new
+ @context = Puppet::Transaction.new(@catalog)
+ end
+
+ describe "when dealing with non-purging resources" do
+ before do
+ @resources = Puppet::Type.type(:resources).new(:name => 'host')
+ end
+
+ it "should not generate any resource" do
+ @resources.generate.should be_empty
+ end
+ end
+
+ describe "when the catalog contains a purging resource" do
+ before do
+ @resources = Puppet::Type.type(:resources).new(:name => 'host', :purge => true)
+ @purgeable_resource = Puppet::Type.type(:host).new(:name => 'localhost', :ip => '127.0.0.1')
+ @catalog.add_resource @resources
+ end
+
+ it "should not generate a duplicate of that resource" do
+ Puppet::Type.type(:host).stubs(:instances).returns [@host1]
+ @catalog.add_resource @host1
+ @resources.generate.collect { |r| r.ref }.should_not include(@host1.ref)
+ end
+
+
+ describe "when generating a purgeable resource" do
+ it "should be included in the generated resources" do
+ Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource]
+ @resources.generate.collect { |r| r.ref }.should include(@purgeable_resource.ref)
+ end
+ end
+
+ describe "when the instance's do not have an ensure property" do
+ it "should not be included in the generated resources" do
+ @no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo')
+ Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource]
+ @resources.generate.collect { |r| r.ref }.should_not include(@no_ensure_resource.ref)
+ end
+ end
+
+ describe "when the instance's ensure property does not accept absent" do
+ it "should not be included in the generated resources" do
+ @no_absent_resource = Puppet::Type.type(:service).new(:name => 'foobar')
+ Puppet::Type.type(:host).stubs(:instances).returns [@no_absent_resource]
+ @resources.generate.collect { |r| r.ref }.should_not include(@no_absent_resource.ref)
+ end
+ end
+
+ describe "when checking the instance fails" do
+ it "should not be included in the generated resources" do
+ @purgeable_resource = Puppet::Type.type(:host).new(:name => 'foobar')
+ Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource]
+ @resources.expects(:check).with(@purgeable_resource).returns(false)
+ @resources.generate.collect { |r| r.ref }.should_not include(@purgeable_resource.ref)
+ end
+ end
+ end
+ end
end
diff --git a/spec/unit/type/tidy.rb b/spec/unit/type/tidy.rb
index caf5b22b7..88e2e280a 100755
--- a/spec/unit/type/tidy.rb
+++ b/spec/unit/type/tidy.rb
@@ -7,6 +7,10 @@ tidy = Puppet::Type.type(:tidy)
describe tidy do
before do
Puppet.settings.stubs(:use)
+
+ # for an unknown reason some of these specs fails when run individually
+ # with a failed expectation on File.lstat in the autoloader.
+ File.stubs(:lstat)
end
it "should use :lstat when stating a file" do
@@ -161,7 +165,7 @@ describe tidy do
Puppet::FileServing::Fileset.stubs(:new).returns @fileset
end
- it "should use a Fileset for recursion" do
+ it "should use a Fileset for infinite recursion" do
Puppet::FileServing::Fileset.expects(:new).with("/what/ever", :recurse => true).returns @fileset
@fileset.expects(:files).returns %w{. one two}
@tidy.stubs(:tidy?).returns false
@@ -169,6 +173,15 @@ describe tidy do
@tidy.generate
end
+ it "should use a Fileset for limited recursion" do
+ @tidy[:recurse] = 42
+ Puppet::FileServing::Fileset.expects(:new).with("/what/ever", :recurse => true, :recurselimit => 42).returns @fileset
+ @fileset.expects(:files).returns %w{. one two}
+ @tidy.stubs(:tidy?).returns false
+
+ @tidy.generate
+ end
+
it "should generate a file resource for every file that should be tidied but not for files that should not be tidied" do
@fileset.expects(:files).returns %w{. one two}
diff --git a/spec/unit/util/log.rb b/spec/unit/util/log.rb
index 4e2c8dcc5..35e6a71e8 100755
--- a/spec/unit/util/log.rb
+++ b/spec/unit/util/log.rb
@@ -13,6 +13,42 @@ describe Puppet::Util::Log do
Puppet::Util::Log.close_all
end
+ describe Puppet::Util::Log::DestConsole do
+ before do
+ @console = Puppet::Util::Log::DestConsole.new
+ end
+
+ it "should colorize if Puppet[:color] is :ansi" do
+ Puppet[:color] = :ansi
+
+ @console.colorize(:alert, "abc").should == "\e[0;31mabc\e[0m"
+ end
+
+ it "should colorize if Puppet[:color] is 'yes'" do
+ Puppet[:color] = "yes"
+
+ @console.colorize(:alert, "abc").should == "\e[0;31mabc\e[0m"
+ end
+
+ it "should htmlize if Puppet[:color] is :html" do
+ Puppet[:color] = :html
+
+ @console.colorize(:alert, "abc").should == "<span style=\"color: FFA0A0\">abc</span>"
+ end
+
+ it "should do nothing if Puppet[:color] is false" do
+ Puppet[:color] = false
+
+ @console.colorize(:alert, "abc").should == "abc"
+ end
+
+ it "should do nothing if Puppet[:color] is invalid" do
+ Puppet[:color] = "invalid option"
+
+ @console.colorize(:alert, "abc").should == "abc"
+ end
+ end
+
describe "instances" do
before do
Puppet::Util::Log.stubs(:newmessage)
diff --git a/spec/unit/util/monkey_patches.rb b/spec/unit/util/monkey_patches.rb
new file mode 100644
index 000000000..335f90b86
--- /dev/null
+++ b/spec/unit/util/monkey_patches.rb
@@ -0,0 +1,103 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+require 'puppet/util/monkey_patches'
+
+describe RDoc do
+ it "should return the call stack if a script is called directly" do
+ stack = [
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:99:in `usage_no_exit'",
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:93:in `usage'",
+ "./puppet/application.rb:295:in `help'",
+ "./puppet/application.rb:207:in `handle_help'",
+ "./puppet/application.rb:141:in `send'",
+ "./puppet/application.rb:141:in `option'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `call'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `catch'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1248:in `order!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1339:in `permute!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1360:in `parse!'",
+ "./puppet/application.rb:262:in `parse_options'",
+ "./puppet/application.rb:214:in `run'",
+ "./puppet/application.rb:306:in `exit_on_fail'",
+ "./puppet/application.rb:214:in `run'",
+ "../bin/puppet:71"
+ ]
+
+ old_dollar_zero = $0
+ $0 = "../bin/puppet"
+
+ # Mocha explodes if you try to mock :caller directly
+ Kernel.expects( :mock_caller ).returns( stack )
+ Kernel.instance_eval { alias orig_caller caller }
+ Kernel.instance_eval { alias caller mock_caller }
+
+ RDoc.caller.must == stack
+
+ $0 = old_dollar_zero
+ Kernel.instance_eval { alias caller orig_caller }
+ end
+
+ it "should return a truncated call stack if a script is called from a rubygems stub" do
+ gem_stack = [
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:99:in `usage_no_exit'",
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:93:in `usage'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:295:in `help'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:207:in `handle_help'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:141:in `send'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:141:in `option'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `call'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `catch'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1248:in `order!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1339:in `permute!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1360:in `parse!'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:262:in `parse_options'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:214:in `run'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:306:in `exit_on_fail'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:214:in `run'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/bin/puppet:71",
+ "/usr/bin/puppet:19:in `load'",
+ "/usr/bin/puppet:19"
+ ]
+
+ real_stack = [
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:99:in `usage_no_exit'",
+ "/usr/lib/ruby/1.8/rdoc/usage.rb:93:in `usage'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:295:in `help'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:207:in `handle_help'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:141:in `send'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:141:in `option'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `call'",
+ "/usr/lib/ruby/1.8/optparse.rb:1267:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `catch'",
+ "/usr/lib/ruby/1.8/optparse.rb:1254:in `parse_in_order'",
+ "/usr/lib/ruby/1.8/optparse.rb:1248:in `order!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1339:in `permute!'",
+ "/usr/lib/ruby/1.8/optparse.rb:1360:in `parse!'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:262:in `parse_options'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:214:in `run'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:306:in `exit_on_fail'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/lib/puppet/application.rb:214:in `run'",
+ "/usr/lib/ruby/gems/1.8/gems/puppet-0.25.1/bin/puppet:71",
+ ]
+
+ old_dollar_zero = $0
+ $0 = '/usr/bin/puppet'
+
+ # Mocha explodes if you try to mock :caller directly
+ Kernel.expects( :mock_caller ).returns( gem_stack )
+ Kernel.instance_eval { alias orig_caller caller }
+ Kernel.instance_eval { alias caller mock_caller }
+
+ RDoc.caller.must == real_stack
+
+ $0 = old_dollar_zero
+ Kernel.instance_eval { alias caller orig_caller }
+ end
+end
+
diff --git a/spec/unit/util/selinux.rb b/spec/unit/util/selinux.rb
index da4686ec4..7e6cdaf30 100755
--- a/spec/unit/util/selinux.rb
+++ b/spec/unit/util/selinux.rb
@@ -61,6 +61,42 @@ describe Puppet::Util::SELinux do
selinux_label_support?('/mnt/nfs/testfile').should be_false
end
+ it "should follow symlinks when determining file systems" do
+ self.stubs(:realpath).with('/mnt/symlink/testfile').returns('/mnt/nfs/dest/testfile')
+
+ selinux_label_support?('/mnt/symlink/testfile').should be_false
+ end
+
+ end
+
+ describe "realpath" do
+ it "should handle files that don't exist" do
+
+ # Since I'm stubbing Pathname.new for this test,
+ # I need to also stub the internal calls to Pathname.new,
+ # which happen in Pathname.dirname and Parthname.basename
+ # I want those to return real Pathname objects,
+ # so I'm creating them before the stub is in place.
+ realpaths = Hash.new {|hash, path| hash[path] = Pathname.new(path) }
+ paths = ['symlink', '/mnt']
+ paths.each { |path| realpaths[path] }
+
+ realpaths['/mnt/symlink'] = stubs "Pathname"
+ realpaths['/mnt/symlink'].stubs(:realpath).returns(realpaths['/mnt/nfs/dest'])
+ realpaths['/mnt/symlink'].stubs(:exist?).returns(true)
+
+ realpaths['/mnt/symlink/nonexistant'] = stubs "Pathname"
+ realpaths['/mnt/symlink/nonexistant'].stubs(:realpath).raises(Errno::ENOENT)
+ realpaths['/mnt/symlink/nonexistant'].stubs(:exist?).returns(false)
+ realpaths['/mnt/symlink/nonexistant'].stubs(:dirname).returns(realpaths['/mnt/symlink'])
+ realpaths['/mnt/symlink/nonexistant'].stubs(:basename).returns(realpaths['nonexistant'])
+
+ realpaths.each do |path, value|
+ Pathname.stubs(:new).with(path).returns(value)
+ end
+
+ realpath('/mnt/symlink/nonexistant').should == '/mnt/nfs/dest/nonexistant'
+ end
end
describe "get_selinux_current_context" do
@@ -158,6 +194,12 @@ describe Puppet::Util::SELinux do
set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_nil
end
+ it "should return nil if selinux_label_support returns false" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:selinux_label_support?).with("/foo").returns false
+ set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_nil
+ end
+
it "should use lsetfilecon to set a context" do
self.expects(:selinux_support?).returns true
Selinux.expects(:lsetfilecon).with("/foo", "user_u:role_r:type_t:s0").returns 0
diff --git a/spec/unit/util/tagging.rb b/spec/unit/util/tagging.rb
index d61ee8ccb..3486f46f2 100755
--- a/spec/unit/util/tagging.rb
+++ b/spec/unit/util/tagging.rb
@@ -89,4 +89,14 @@ describe Puppet::Util::Tagging, "when adding tags" do
it "should indicate when the object is not tagged with a provided tag" do
@tagger.should_not be_tagged("one")
end
+
+ it "should indicate when the object is tagged with any tag in an array" do
+ @tagger.tag("one")
+ @tagger.should be_tagged("one","two","three")
+ end
+
+ it "should indicate when the object is not tagged with any tag in an array" do
+ @tagger.tag("one")
+ @tagger.should_not be_tagged("two","three")
+ end
end
diff --git a/tasks/rake/git_workflow.rake b/tasks/rake/git_workflow.rake
new file mode 100644
index 000000000..b2f96c603
--- /dev/null
+++ b/tasks/rake/git_workflow.rake
@@ -0,0 +1,121 @@
+# This set of tasks helps automate the workflow as described on
+# http://reductivelabs.com/trac/puppet/wiki/Development/DevelopmentLifecycle
+
+
+def find_start(start)
+# This is a case statement, as we might want to map certain
+# git tags to starting points that are not currently in git.
+ case start
+ when nil?:
+ when @next_release: return "master"
+ else return start
+ end
+end
+
+desc "Set up git for working with Puppet"
+task :git_setup do
+ # This should be changed as new versions get released
+ @next_release = '0.26.x'
+ @remote = {}
+ default_remote = {}
+ default_remote[:url] = 'git://github.com/reductivelabs/puppet'
+ default_remote[:name] = 'origin'
+ @remote[:name] = %x{git config puppet.defaultremote}.chomp
+ @remote[:name] = @remote[:name].empty? ? default_remote[:name] : @remote[:name]
+ @remote[:url] = default_remote[:url] if @remote[:name] == default_remote[:name]
+ default_fetch = '+refs/heads/*:refs/remotes/puppet/*'
+ @remote[:fetch] = %x{git config puppet.#{@remote[:name]}.fetch}.chomp
+ @remote[:fetch] = @remote[:fetch].empty? ? default_fetch : @remote[:fetch]
+end
+
+desc "Start work on a feature"
+task :start_feature, [:feature,:remote,:branch] => :git_setup do |t, args|
+ args.with_defaults(:remote => @remote[:name])
+ args.with_defaults(:branch => @next_release)
+ start_at = find_start(args.branch)
+ branch = "feature/#{start_at}/#{args.feature}"
+ sh "git checkout -b #{branch} #{start_at}" do |ok, res|
+ if ! ok
+ raise <<EOS
+Was not able to create branch for #{args.feature} on branch #{args.branch}, starting at #{start_at}: error code was: #{res.exitstatus}
+EOS
+ end
+ end
+ sh "git config branch.#{branch}.remote #{args.remote}" do |ok, res|
+ raise "Could not set remote: #{$?}" unless ok
+ end
+
+ sh "git config branch.#{branch}.merge refs/heads/#{branch}" do |ok, res|
+ raise "Could not configure merge: #{$?}" unless ok
+ end
+end
+
+desc "Do git prep to start work on a Redmine ticket"
+task :start_ticket, [:ticket, :remote, :branch] => :git_setup do |t, args|
+ args.with_defaults(:remote => @remote[:name])
+ args.with_defaults(:branch => @next_release)
+ start_at = find_start(args.branch)
+ branch = "tickets/#{start_at}/#{args.ticket}"
+ sh "git checkout -b #{branch} #{start_at}" do |ok, res|
+ unless ok
+ raise <<EOS
+Was not able to create branch for ticket #{args.ticket} on branch #{args.branch}, starting at #{start_at}: error code was: #{$?}
+Git command used was: #{command}
+EOS
+ end
+ end
+ sh "git config branch.#{branch}.remote #{args.remote}" do |ok, res|
+ raise "Could not set remote: #{$?}" unless ok
+ end
+
+ sh "git config branch.#{branch}.merge refs/heads/#{branch}" do |ok, res|
+ raise "Could not configure merge: #{$?}" unless ok
+ end
+end
+
+# This isn't very useful by itself, but we might enhance it later, or use it
+# in a dependency for a more complex task.
+desc "Push out changes"
+task :push_changes, [:remote] do |t, arg|
+ branch = %x{git branch | grep "^" | awk '{print $2}'}
+ sh "git push #{arg.remote} #{branch}" do |ok, res|
+ raise "Unable to push to #{arg.remote}" unless ok
+ end
+end
+
+desc "Send patch information to the puppet-dev list"
+task :mail_patches do
+ if Dir.glob("00*.patch").length > 0
+ raise "Patches already exist matching '00*.patch'; clean up first"
+ end
+
+ unless %x{git status} =~ /On branch (.+)/
+ raise "Could not get branch from 'git status'"
+ end
+ branch = $1
+
+ unless branch =~ %r{^([^\/]+)/([^\/]+)/([^\/]+)$}
+ raise "Branch name does not follow <type>/<parent>/<name> model; cannot autodetect parent branch"
+ end
+
+ type, parent, name = $1, $2, $3
+
+ # Create all of the patches
+ sh "git format-patch -C -M -s -n --subject-prefix='PATCH/puppet' #{parent}..HEAD"
+
+ # And then mail them out.
+
+ # If we've got more than one patch, add --compose
+ if Dir.glob("00*.patch").length > 1
+ compose = "--compose"
+ else
+ compose = ""
+ end
+
+ # Now send the mail.
+ sh "git send-email #{compose} --no-signed-off-by-cc --suppress-from --to puppet-dev@googlegroups.com 00*.patch"
+
+ # Finally, clean up the patches
+ sh "rm 00*.patch"
+end
+
diff --git a/tasks/rake/mail_patches.rake b/tasks/rake/mail_patches.rake
deleted file mode 100644
index 82455e87f..000000000
--- a/tasks/rake/mail_patches.rake
+++ /dev/null
@@ -1,35 +0,0 @@
-desc "Send patch information to the puppet-dev list"
-task :mail_patches do
- if Dir.glob("00*.patch").length > 0
- raise "Patches already exist matching '00*.patch'; clean up first"
- end
-
- unless %x{git status} =~ /On branch (.+)/
- raise "Could not get branch from 'git status'"
- end
- branch = $1
-
- unless branch =~ %r{^([^\/]+)/([^\/]+)/([^\/]+)$}
- raise "Branch name does not follow <type>/<parent>/<name> model; cannot autodetect parent branch"
- end
-
- type, parent, name = $1, $2, $3
-
- # Create all of the patches
- sh "git format-patch -C -M -s -n --subject-prefix='PATCH/puppet' #{parent}..HEAD"
-
- # And then mail them out.
-
- # If we've got more than one patch, add --compose
- if Dir.glob("00*.patch").length > 1
- compose = "--compose"
- else
- compose = ""
- end
-
- # Now send the mail.
- sh "git send-email #{compose} --no-signed-off-by-cc --suppress-from --to puppet-dev@googlegroups.com 00*.patch"
-
- # Finally, clean up the patches
- sh "rm 00*.patch"
-end
diff --git a/tasks/rake/sign.rake b/tasks/rake/sign.rake
new file mode 100644
index 000000000..2eed60df0
--- /dev/null
+++ b/tasks/rake/sign.rake
@@ -0,0 +1,14 @@
+desc "Sign to the package with the Reductive Labs release key"
+task :sign_packages do
+
+version = Puppet::PUPPETVERSION
+
+# Sign package
+
+sh "gpg --homedir $HOME/release_key --detach-sign --output pkg/puppet-#{version}.tar.gz.sign --armor pkg/puppet-#{version}.tar.gz"
+
+# Sign gem
+
+sh "gpg --homedir $HOME/release_key --detach-sign --output pkg/puppet-#{version}.gem.sign --armor pkg/puppet-#{version}.gem"
+
+end
diff --git a/test/data/providers/ssh_authorized_key/parsed/authorized_keys b/test/data/providers/ssh_authorized_key/parsed/authorized_keys
index a2a85d93c..b22329dca 100644
--- a/test/data/providers/ssh_authorized_key/parsed/authorized_keys
+++ b/test/data/providers/ssh_authorized_key/parsed/authorized_keys
@@ -4,3 +4,4 @@ from="192.168.1.1",command="/bin/false",no-pty,no-port-forwarding ssh-dss AAAAB3
from="192.168.1.1, www.reductivelabs.com",command="/bin/false",no-pty,no-port-forwarding ssh-dss AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVe+esFfd3qWBseb83PoFX63geZJAg6bjV4/Rdn1zEoa9EO2QyUdYUen4+rpsh3vVKZ6HFNsn3+W5+kPYgE1F/N4INqkbjY3sqCkP/W1BL9+sbVVbuJFAAAAFQCfjWDk5XhvGUkPjNWWVqltBYzHtwAAAIEAg/XL7ky7x9Ad5banzPFAfmM+DGFe0A/JEbLDjKmr5KBM5x4RFohtEvZ8ECuVGUOqBWdgAjyYwsG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4knEl+mNfOLq+FH0011UhecOiqTcESMzQDtgQ1vJh2VchElBLjl3x/ZugAAACAAh5jGQC338t5ObP8trSlOefkx0sXmmEzUbo3Mt8mGUuGJPx8m+X0L8Xd+l5rQxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaLZq7m/RmsWYvoLT3jebBlpvvQE8YlI= Francois Deppierraz
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2Vi+TdC3iOGYcIo5vGTvC9P9rjHl9RxCuZmSfn+YDFQ35RXf0waijtjp9I7GYh6R4hBjA5z0u/Pzi95LET5NfRM0Gdc0DJyvBI7K+ALBxIT383Iz6Yz4iKxe1TEJgHGM2he4+7BHkjc3kdIZqIpZjucCk4VsXSxujO4MKKvtaKK2l+kahlLQHHw/vZkDpIgL52iGVsjW9l8RLJaKHZ4mDHJN/Q/Rzn2W4EvcdHUzwhvGMwZlm8clDwITBrSsawYtnivJrQSYcmTRqJuS8wprNDrLIhTGjrwFg5WpruUuMt6fLuCqwe6TeEL+nh3DQ4g554c5aRp3oU6LGBKTvNZGWQ== francois@korn
ssh-dss AAAAB3NzaC1kc3MAAACBAMPpCYnjywOemd8LqbbmC+bePNR3/H1rXsiFwjSLhYE3bbOpvclvOzN1DruFc34m0FopVnMkP+aubjdIYF8pijl+5hg9ggB7Kno2dl0Dd1rGN/swvmhA8OpLAQv7Qt7UnXKVho3as08zYZsrHxYFu0wlnkdbsv4cy4aXyQKd4MPVAAAAFQDSyQFWg8Qt3wU05buhZ10psoR7tQAAAIEAmAhguXwUnI3P2FF5NAW/mpJUmUERdL4pyZARUyAgpf7ezwrh9TJqrvGTQNBF97Xqaivyncm5JWQdMIsTBxEFaXZGkmBta02KnWcn447qvIh7iv8XpNL6M9flCkBEZOJ4t9El0ytTSHHaiCz8A20Et+E8evWyi1kXkFDt8ML2dGgAAACBAK0X4ympbdEjgV/ZyOc+BU22u7vOnfSOUJmyar4Ax1MIDNnoyNWKnGvxRutydQcQOKQHZEU0fE8MhPFn6nLF6CoVfEl/oz0EYz3hjV4WPFpHrF5DY/rhvNj8iuneKJ5P0dy/rG6m5qey25PnHyGFVoIRlkHJvBCJT40dHs40YEjI francois@korn
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAut8aOSxenjOqF527dlsdHWV4MNoAsX14l9M297+SQXaQ5Z3BedIxZaoQthkDALlV/25A1COELrg9J2MqJNQc8Xe9XQOIkBQWWinUlD/BXwoOTWEy8C8zSZPHZ3getMMNhGTBO+q/O+qiJx3y5cA4MTbw2zSxukfWC87qWwcZ64UUlegIM056vPsdZWFclS9hsROVEa57YUMrehQ1EGxT4Z5j6zIopufGFiAPjZigq/vqgcAqhAKP6yu4/gwO6S9tatBeEjZ8fafvj1pmvvIplZeMr96gHE7xS3pEEQqnB3nd4RY7AF6j9kFixnsytAUO7STPh/M3pLiVQBN89TvWPQ==