summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-10-09 15:51:05 +0200
committerLuke Kanies <luke@madstop.com>2008-10-09 15:51:05 +0200
commit9ef6209b3ed1269f7cd1e6a8d0f189f6b5712800 (patch)
tree3c786b42679f3bea18979aceb8e3bf2a5184f366
parentb96bdc6a63f7be6b724c2aa7ad0ea007cba81718 (diff)
parent0fff7d76e89a650f5d2e78b2c69b30635880c36b (diff)
downloadpuppet-9ef6209b3ed1269f7cd1e6a8d0f189f6b5712800.tar.gz
puppet-9ef6209b3ed1269f7cd1e6a8d0f189f6b5712800.tar.xz
puppet-9ef6209b3ed1269f7cd1e6a8d0f189f6b5712800.zip
Merge branch '0.24.x' of git://github.com/jamtur01/puppet into 0.24.x
-rw-r--r--CHANGELOG65
-rw-r--r--Rakefile36
-rwxr-xr-xbin/puppet43
-rw-r--r--ext/passenger/README63
-rw-r--r--ext/passenger/apache2.conf29
-rw-r--r--ext/passenger/config.ru40
-rw-r--r--lib/puppet/defaults.rb7
-rw-r--r--lib/puppet/file_serving/fileset.rb4
-rw-r--r--lib/puppet/file_serving/metadata.rb6
-rw-r--r--lib/puppet/module.rb22
-rwxr-xr-xlib/puppet/network/handler/fileserver.rb84
-rw-r--r--lib/puppet/network/handler/master.rb2
-rw-r--r--lib/puppet/network/http_server/rack.rb148
-rw-r--r--lib/puppet/network/xmlrpc/client.rb10
-rw-r--r--lib/puppet/node.rb8
-rw-r--r--lib/puppet/node/environment.rb18
-rw-r--r--lib/puppet/parser/ast.rb6
-rw-r--r--lib/puppet/parser/ast/arithmetic_operator.rb41
-rw-r--r--lib/puppet/parser/ast/boolean_operator.rb48
-rw-r--r--lib/puppet/parser/ast/collexpr.rb7
-rw-r--r--lib/puppet/parser/ast/comparison_operator.rb37
-rw-r--r--lib/puppet/parser/ast/minus.rb23
-rw-r--r--lib/puppet/parser/ast/nop.rb11
-rw-r--r--lib/puppet/parser/ast/not.rb19
-rw-r--r--lib/puppet/parser/ast/resource_override.rb39
-rw-r--r--lib/puppet/parser/ast/resource_reference.rb16
-rw-r--r--lib/puppet/parser/grammar.ra106
-rw-r--r--lib/puppet/parser/lexer.rb17
-rw-r--r--lib/puppet/parser/parser.rb1595
-rw-r--r--lib/puppet/parser/scope.rb23
-rw-r--r--lib/puppet/property/list.rb78
-rw-r--r--lib/puppet/provider/nameservice.rb63
-rw-r--r--lib/puppet/provider/nameservice/directoryservice.rb15
-rw-r--r--lib/puppet/provider/nameservice/netinfo.rb14
-rw-r--r--lib/puppet/provider/nameservice/objectadd.rb11
-rwxr-xr-xlib/puppet/provider/package/apt.rb33
-rwxr-xr-xlib/puppet/provider/package/dpkg.rb82
-rw-r--r--lib/puppet/provider/package/portage.rb2
-rwxr-xr-xlib/puppet/provider/package/rpm.rb9
-rw-r--r--lib/puppet/provider/package/rug.rb4
-rw-r--r--lib/puppet/provider/package/yumhelper.py103
-rw-r--r--lib/puppet/provider/selboolean/getsetsebool.rb47
-rw-r--r--lib/puppet/provider/selmodule/semodule.rb143
-rwxr-xr-xlib/puppet/provider/service/redhat.rb2
-rw-r--r--lib/puppet/provider/ssh_authorized_key/parsed.rb6
-rw-r--r--lib/puppet/provider/user/user_role_add.rb89
-rw-r--r--lib/puppet/sslcertificates/support.rb3
-rw-r--r--lib/puppet/type.rb36
-rw-r--r--lib/puppet/type/file.rb1
-rwxr-xr-xlib/puppet/type/file/checksum.rb4
-rwxr-xr-xlib/puppet/type/file/group.rb73
-rw-r--r--lib/puppet/type/file/selcontext.rb87
-rwxr-xr-xlib/puppet/type/group.rb8
-rw-r--r--lib/puppet/type/selboolean.rb29
-rw-r--r--lib/puppet/type/selmodule.rb50
-rw-r--r--lib/puppet/type/ssh_authorized_key.rb6
-rwxr-xr-xlib/puppet/type/user.rb184
-rw-r--r--lib/puppet/type/zone.rb6
-rw-r--r--lib/puppet/util.rb6
-rwxr-xr-xlib/puppet/util/filetype.rb7
-rw-r--r--lib/puppet/util/log.rb49
-rw-r--r--lib/puppet/util/metric.rb32
-rwxr-xr-xlib/puppet/util/posix.rb22
-rw-r--r--lib/puppet/util/selinux.rb136
-rw-r--r--lib/puppet/util/settings.rb8
-rw-r--r--lib/puppet/util/user_attr.rb21
-rwxr-xr-xspec/integration/provider/package.rb26
-rw-r--r--spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb5
-rw-r--r--spec/monkey_patches/alias_should_to_must.rb5
-rwxr-xr-xspec/unit/file_serving/fileset.rb9
-rwxr-xr-xspec/unit/file_serving/metadata.rb18
-rwxr-xr-xspec/unit/module.rb13
-rw-r--r--spec/unit/network/handler/fileserver.rb179
-rw-r--r--spec/unit/network/xmlrpc/client.rb13
-rwxr-xr-xspec/unit/node.rb19
-rwxr-xr-xspec/unit/node/environment.rb52
-rwxr-xr-xspec/unit/parser/ast/arithmetic_operator.rb73
-rwxr-xr-xspec/unit/parser/ast/boolean_operator.rb53
-rwxr-xr-xspec/unit/parser/ast/collexpr.rb92
-rwxr-xr-xspec/unit/parser/ast/comparison_operator.rb52
-rwxr-xr-xspec/unit/parser/ast/minus.rb36
-rwxr-xr-xspec/unit/parser/ast/nop.rb20
-rwxr-xr-xspec/unit/parser/ast/not.rb30
-rwxr-xr-xspec/unit/parser/ast/resource_override.rb51
-rwxr-xr-xspec/unit/parser/ast/resource_reference.rb63
-rwxr-xr-xspec/unit/parser/lexer.rb57
-rwxr-xr-xspec/unit/parser/parser.rb113
-rwxr-xr-xspec/unit/parser/scope.rb50
-rw-r--r--spec/unit/property/list.rb147
-rwxr-xr-xspec/unit/provider/package/apt.rb138
-rwxr-xr-xspec/unit/provider/package/dpkg.rb163
-rwxr-xr-xspec/unit/provider/selboolean.rb37
-rw-r--r--spec/unit/provider/selmodule-example.ppbin0 -> 256 bytes
-rwxr-xr-xspec/unit/provider/selmodule.rb66
-rw-r--r--spec/unit/provider/user/user_role_add.rb131
-rwxr-xr-xspec/unit/type.rb73
-rwxr-xr-xspec/unit/type/file.rb8
-rwxr-xr-xspec/unit/type/file/group.rb118
-rw-r--r--spec/unit/type/file/selinux.rb82
-rwxr-xr-xspec/unit/type/selboolean.rb47
-rwxr-xr-xspec/unit/type/selmodule.rb18
-rwxr-xr-xspec/unit/type/user.rb205
-rwxr-xr-xspec/unit/util/log.rb153
-rwxr-xr-xspec/unit/util/metric.rb95
-rwxr-xr-xspec/unit/util/posix.rb256
-rw-r--r--spec/unit/util/selinux.rb174
-rwxr-xr-xspec/unit/util/settings.rb15
-rw-r--r--spec/unit/util/user_attr.rb47
-rw-r--r--test/data/providers/ssh_authorized_key/parsed/authorized_keys13
-rw-r--r--test/data/snippets/arithmetic_expression.pp8
-rw-r--r--test/data/snippets/emptyifelse.pp9
-rw-r--r--test/data/snippets/ifexpression.rb6
-rwxr-xr-xtest/language/ast/resource_reference.rb28
-rwxr-xr-xtest/language/functions.rb2
-rw-r--r--test/lib/puppettest/reporttesting.rb2
-rw-r--r--test/lib/puppettest/runnable_test.rb2
-rwxr-xr-xtest/network/client/master.rb8
-rwxr-xr-xtest/network/handler/fileserver.rb8
-rwxr-xr-xtest/network/handler/master.rb4
-rwxr-xr-xtest/other/report.rb6
-rwxr-xr-xtest/other/transactions.rb2
-rwxr-xr-xtest/ral/providers/group.rb27
-rwxr-xr-xtest/ral/providers/package.rb31
-rwxr-xr-xtest/ral/providers/package/apt.rb169
-rwxr-xr-xtest/ral/providers/package/aptitude.rb3
-rwxr-xr-xtest/ral/providers/package/aptrpm.rb4
-rwxr-xr-xtest/ral/providers/package/dpkg.rb64
-rwxr-xr-xtest/ral/providers/user.rb16
-rwxr-xr-xtest/ral/type/filesources.rb4
-rwxr-xr-xtest/ral/type/mailalias.rb3
-rwxr-xr-xtest/ral/type/user.rb50
-rwxr-xr-xtest/util/log.rb59
-rwxr-xr-xtest/util/posixtest.rb182
133 files changed, 5814 insertions, 1930 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c54aa6225..d76604f6d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,68 @@
-0.24.x
+0.24.6
+ Fixed #1639 - uninitialized constant Puppet::Type::User::ProviderUseradd
+
+ Fixed #1637 - With an inexistant (global) templatedir, modules
+ can't access their templates
+
+ Fixed #1202 - Collection attribute matching doesn't parse arrays
+
+ Fixed #1473 - Puppetd stops with error after puppetmasterd
+ is unavailable
+
+ Fixed #1354 - yum provider problems with RHEL 3
+
+ Fixed #1633 - Added support for --detailed-exits to bin/puppet
+
+ Fixed #381 - Allow Allow multiple overrides in one statement
+
+ Fixing #947 - pluginsync no longer fails poorly when no plugins exist
+
+ Fixed #981 - Removed 'Adding aliases' info message
+
+ Fixing #1089 - Log messages are now tagged with the log level,
+ making it easier to match messages in the 'tagmail' report.
+
+ Fixing #1098 - Multiline strings now correctly increment the line count
+
+ Fixing #1614 - Environments no longer have to be listed out
+
+ Fixed #1628 - Changed node search to use certname rather than Facter
+ hostname
+
+ Fixed #1613 - The client environment will be substituted when looking
+ up settings.
+
+ Updated puppet binary documentation
+
+ Feature #1624 - Added RBAC roles to solaris user provider
+
+ Fixed #1586 - Specifying "fully qualified" package names in Gentoo
+
+ Fixed #1620 - Add 'sles' to Puppet confines when 'suse' is used
+
+ Fixed #1585 - Allow complex 'if' and variable expressions
+
+ Fixed #1564 - Saving File#checksum to state.yaml broken
+
+ Fixed #1603 - Added support for running Puppet inside a Rack application
+ (mod_rails) with Passenger and Apache
+
+ Fixed #1596 - Deploying file resources with ++ generates error
+
+ Modified the group and zone resource types to no longer call
+ 'currentpropvalues' as a means of setting all values to absent.
+ There should be no behaviour change from this change.
+
+ Modified the behaviour of resource-level 'retrieve' -- it only
+ calls 'retrieve' on each property if the resource exists.
+
+ Fixed #1622 - Users and their groups should again add in one transaction
+
+ Fixed #791 - You should now be able to create and find a user/group in one transaction.
+
Fixed #1610 - Raise "Filebucketed" messages to Notice priority
+
+ FIxed #1530 - ssh_authorized_keys provider does not crash anymore on SSH type 1 keys
Added a number of confines to package providers
diff --git a/Rakefile b/Rakefile
index a934fff81..45d365247 100644
--- a/Rakefile
+++ b/Rakefile
@@ -161,3 +161,39 @@ desc "Run the unit tests"
task :unit do
sh "cd test; rake"
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 #{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-chain-reply-to --no-signed-off-by-cc --suppress-from --no-thread --to puppet-dev@googlegroups.com 00*.patch"
+
+ # Finally, clean up the patches
+ sh "rm 00*.patch"
+end
diff --git a/bin/puppet b/bin/puppet
index 0e64b1cf3..f3d8c252f 100755
--- a/bin/puppet
+++ b/bin/puppet
@@ -3,18 +3,18 @@
#
# = Synopsis
#
-# Run a stand-alone +puppet+ script.
+# Run a stand-alone +puppet+ manifest.
#
# = Usage
#
# puppet [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose]
-# [-l|--logdest <file>] <file>
+# [--detailed-exitcodes] [-l|--logdest <file>] <file>
#
# = Description
#
-# This is the standalone puppet execution script; use it to execute
-# individual scripts that you write. If you need to execute site-wide
-# scripts, use +puppetd+ and +puppetmasterd+.
+# This is the standalone puppet execution tool; use it to execute
+# individual manifests that you write. If you need to execute site-wide
+# manifests, use +puppetd+ and +puppetmasterd+.
#
# = Options
#
@@ -31,6 +31,11 @@
# debug::
# Enable full debugging.
#
+# detailed-exitcodes::
+# Provide transaction information via exit codes. If this is enabled, an exit
+# code of '2' means there were changes, and an exit code of '4' means that there
+# were failures during the transaction.
+#
# help::
# Print this help message
#
@@ -48,7 +53,7 @@
#
# = Example
#
-# puppet -l /tmp/script.log script.pp
+# puppet -l /tmp/manifest.log manifest.pp
#
# = Author
#
@@ -72,6 +77,7 @@ options = [
[ "--loadclasses", "-L", GetoptLong::NO_ARGUMENT ],
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
[ "--use-nodes", GetoptLong::NO_ARGUMENT ],
+ [ "--detailed-exitcodes", GetoptLong::NO_ARGUMENT ],
[ "--version", "-V", GetoptLong::NO_ARGUMENT ]
]
@@ -87,7 +93,8 @@ options = {
:logfile => false,
:loadclasses => false,
:logset => false,
- :code => nil
+ :code => nil,
+ :detailed_exits => false,
}
@@ -118,6 +125,8 @@ begin
options[:code] = arg
when "--loadclasses"
options[:loadclasses] = true
+ when "--detailed-exitcodes"
+ options[:detailed_exits] = true
when "--logdest"
begin
Puppet::Util::Log.newdestination(arg)
@@ -183,11 +192,12 @@ if Puppet[:parseonly]
end
# Collect our facts.
-facts = Puppet::Node::Facts.find("me")
-facts.name = facts.values["hostname"]
+facts = Puppet::Node::Facts.find(Puppet[:certname])
# Find our Node
-node = Puppet::Node.find(facts.name)
+unless node = Puppet::Node.find(Puppet[:certname])
+ raise "Could not find node %s" % Puppet[:certname]
+end
# Merge in the facts.
node.merge(facts.values)
@@ -207,6 +217,7 @@ end
begin
# Compile our catalog
+ starttime = Time.now
catalog = Puppet::Node::Catalog.find(node.name, :use_node => node)
# Translate it to a RAL catalog
@@ -216,8 +227,18 @@ begin
catalog.finalize
+ catalog.retrieval_duration = Time.now - starttime
+
# And apply it
- catalog.apply
+ transaction = catalog.apply
+
+ status = 0
+ if not Puppet[:noop] and options[:detailed_exits] then
+ transaction.generate_report
+ status |= 2 if transaction.report.metrics["changes"][:total] > 0
+ status |= 4 if transaction.report.metrics["resources"][:failed] > 0
+ end
+ exit(status)
rescue => detail
if Puppet[:trace]
puts detail.backtrace
diff --git a/ext/passenger/README b/ext/passenger/README
new file mode 100644
index 000000000..fcdcb913a
--- /dev/null
+++ b/ext/passenger/README
@@ -0,0 +1,63 @@
+
+PUPPETMASTER INSIDE APACHE & PASSENGER
+======================================
+
+This is about running a puppetmaster inside Apache.
+
+Please also see the docs at http://reductivelabs.com/trac/puppet/wiki/UsingPassenger
+for further information.
+
+
+WHAT IS IT?
+===========
+
+Passenger [1] (AKA mod_rails or mod_rack) is an Apache 2.x Extension for
+serving Rails or Rack applications.
+
+This extension allows running a puppetmasterd as a Rack application;
+it has only been tested with Passenger.
+
+
+SHORT INSTALLATION INSTRUCTIONS
+===============================
+
+Make sure puppetmasterd ran at least once, so the SSL certificates
+got set up.
+
+Install Rack:
+ gem install -v 0.4.0 rack
+
+Install Apache and Passenger:
+ apt-get install apache2
+ gem install passenger
+ passenger-install-apache2-module
+ (See the Passenger installation instructions [2] for details.)
+
+Enable Apache modules:
+ a2enmod ssl
+ a2enmod headers
+
+Configure Apache:
+ cp apache2.conf /etc/apache2/conf.d/puppetmasterd
+ vim /etc/apache2/conf.d/puppetmasterd (replace the server hostnames)
+
+Install the rack application [3]:
+ mkdir -p /usr/share/puppet/rack/puppetmasterd
+ mkdir /usr/share/puppet/rack/puppetmasterd/public /usr/share/puppet/rack/puppetmasterd/tmp
+ cp config.ru /usr/share/puppet/rack/puppetmasterd
+ chown puppet /usr/share/puppet/rack/puppetmasterd/config.ru
+
+Go:
+/etc/init.d/apache2 restart
+
+
+
+[1] http://www.modrails.com/
+
+[2] http://www.modrails.com/install.html
+
+[3] Passenger will not let applications run as root or the Apache user,
+instead an implicit setuid will be done, to the user whom owns
+config.ru. Therefore, config.ru shall be owned by the puppet user.
+
+
diff --git a/ext/passenger/apache2.conf b/ext/passenger/apache2.conf
new file mode 100644
index 000000000..6a8a974d7
--- /dev/null
+++ b/ext/passenger/apache2.conf
@@ -0,0 +1,29 @@
+Listen 8140
+<VirtualHost *:8140>
+ SSLEngine on
+ SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
+ SSLCertificateFile /var/lib/puppet/ssl/certs/puppet-server.inqnet.at.pem
+ SSLCertificateKeyFile /var/lib/puppet/ssl/private_keys/puppet-server.inqnet.at.pem
+ SSLCertificateChainFile /var/lib/puppet/ssl/ca/ca_crt.pem
+ SSLCACertificateFile /var/lib/puppet/ssl/ca/ca_crt.pem
+ # If Apache complains about invalid signatures on the CRL, you can try disabling
+ # CRL checking by commenting the next line.
+ SSLCARevocationFile /var/lib/puppet/ssl/ca/ca_crl.pem
+ SSLVerifyClient optional
+ SSLVerifyDepth 1
+ SSLOptions +StdEnvVars
+
+ # The following client headers allow the same configuration to work with Pound.
+ RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
+ RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
+ RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
+
+ RackAutoDetect On
+ DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
+ <Directory /usr/share/puppet/rack/puppetmasterd/>
+ Options None
+ AllowOverride None
+ Order allow,deny
+ allow from all
+ </Directory>
+</VirtualHost>
diff --git a/ext/passenger/config.ru b/ext/passenger/config.ru
new file mode 100644
index 000000000..86082928a
--- /dev/null
+++ b/ext/passenger/config.ru
@@ -0,0 +1,40 @@
+# Author: Christian Hofstaedtler <hofstaedtler@inqnet.at>
+# Copyright (c) 2007 Luke Kanies, 2008 Christian Hofstaedtler
+#
+# This file is mostly based on puppetmasterd, which is part of
+# the standard puppet distribution.
+
+require 'rack'
+require 'puppet'
+require 'puppet/network/http_server/rack'
+
+# startup code from bin/puppetmasterd
+Puppet.parse_config
+Puppet::Util::Log.level = :info
+Puppet::Util::Log.newdestination(:syslog)
+# A temporary solution, to at least make the master work for now.
+Puppet::Node::Facts.terminus_class = :yaml
+# Cache our nodes in yaml. Currently not configurable.
+Puppet::Node.cache_class = :yaml
+
+# The list of handlers running inside this puppetmaster
+handlers = {
+ :Status => {},
+ :FileServer => {},
+ :Master => {},
+ :CA => {},
+ :FileBucket => {},
+ :Report => {}
+}
+
+# Fire up the Rack-Server instance
+server = Puppet::Network::HTTPServer::Rack.new(handlers)
+
+# prepare the rack app
+app = proc do |env|
+ server.process(env)
+end
+
+# Go.
+run app
+
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index a2900fd43..e1b6dc423 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -122,16 +122,11 @@ module Puppet
namespaces and methods. This can be used as a coarse-grained
authorization system for both ``puppetd`` and ``puppetmasterd``."
],
- :environments => ["production,development", "The valid environments for Puppet clients.
- This is more useful as a server-side setting than client, but any
- environment chosen must be in this list. Values should be
- separated by a comma."],
:environment => {:default => "production", :desc => "The environment Puppet is running in. For clients
(e.g., ``puppetd``) this determines the environment itself, which
is used to find modules and much more. For servers (i.e.,
``puppetmasterd``) this provides the default environment for nodes
- we know nothing about.",
- :hook => proc { |value| raise(ArgumentError, "Invalid environment %s" % value) unless Puppet::Node::Environment.valid?(value) }
+ we know nothing about."
},
:diff_args => ["", "Which arguments to pass to the diff command when printing differences between files."],
:diff => ["diff", "Which diff command to use when printing differences between files."],
diff --git a/lib/puppet/file_serving/fileset.rb b/lib/puppet/file_serving/fileset.rb
index fe54350b1..3cb76317d 100644
--- a/lib/puppet/file_serving/fileset.rb
+++ b/lib/puppet/file_serving/fileset.rb
@@ -20,7 +20,7 @@ class Puppet::FileServing::Fileset
# Now strip off the leading path, so each file becomes relative, and remove
# any slashes that might end up at the beginning of the path.
- result = files.collect { |file| file.sub(%r{^#{@path}/*}, '') }
+ result = files.collect { |file| file.sub(%r{^#{Regexp.escape(@path)}/*}, '') }
# And add the path itself.
result.unshift(".")
@@ -120,7 +120,7 @@ class Puppet::FileServing::Fileset
return result
end
-
+ public
# Stat a given file, using the links-appropriate method.
def stat(path)
unless defined?(@stat_method)
diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb
index beecaef48..b277955ac 100644
--- a/lib/puppet/file_serving/metadata.rb
+++ b/lib/puppet/file_serving/metadata.rb
@@ -60,10 +60,10 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::FileBase
case stat.ftype
when "file":
- @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, real_path)
+ @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, real_path).to_s
when "directory": # Always just timestamp the directory.
- sumtype = @checksum_type.to_s =~ /time/ ? @checksum_type : "ctime"
- @checksum = ("{%s}" % sumtype) + send("%s_file" % sumtype, path).to_s
+ @checksum_type = "ctime"
+ @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, path).to_s
when "link":
@destination = File.readlink(real_path)
else
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index b34f2f8b0..9385812b1 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -73,17 +73,23 @@ class Puppet::Module
end
template_paths = templatepath(environment)
- default_template_path = File::join(template_paths.first, template)
+ if template_paths
+ # If we can find the template in :templatedir, we return that.
+ td_file = template_paths.collect { |path|
+ File::join(path, template)
+ }.find { |f| File.exists?(f) }
- # If we can find the template in :templatedir, we return that.
- td_file = template_paths.collect { |path|
- File::join(path, template)
- }.find { |f| File.exists?(f) }
-
- return td_file unless td_file == nil
+ return td_file unless td_file == nil
+ end
td_file = find_template_for_module(template, environment)
- td_file ||= default_template_path
+
+ # check in the default template dir, if there is one
+ if td_file.nil?
+ raise Puppet::Error, "No valid template directory found, please check templatedir settings" if template_paths.nil?
+ td_file = File::join(template_paths.first, template)
+ end
+ td_file
end
def self.find_template_for_module(template, environment = nil)
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 3e62cdbd9..815d0ba82 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -70,7 +70,9 @@ class Puppet::Network::Handler
mount.debug("Describing %s for %s" % [url, client]) if client
# use the mount to resolve the path for us.
- metadata = Puppet::FileServing::Metadata.new(url, :path => mount.file_path(path, client), :links => links)
+ return "" unless full_path = mount.file_path(path, client)
+
+ metadata = Puppet::FileServing::Metadata.new(url, :path => full_path, :links => links)
return "" unless metadata.exist?
@@ -651,55 +653,38 @@ class Puppet::Network::Handler
# and "bad batch".
#
def list(relpath, recurse, ignore, client = nil)
- reclist(file_path(relpath, client), nil, recurse, ignore)
- end
-
- # Recursively list the files in this tree.
- def reclist(basepath, abspath, recurse, ignore)
- abspath = basepath if abspath.nil?
- relpath = abspath.sub(%r{^#{basepath}}, '')
- relpath = "/#{relpath}" if relpath[0] != ?/ #/
-
- return unless FileTest.exists?(abspath)
-
- desc = [relpath]
-
- ftype = File.stat(abspath).ftype
-
- desc << ftype
- if recurse.is_a?(Integer)
- recurse -= 1
+ abspath = file_path(relpath, client)
+ if FileTest.exists?(abspath)
+ if FileTest.directory?(abspath) and recurse
+ return reclist(abspath, recurse, ignore)
+ else
+ return [["/", File.stat(abspath).ftype]]
+ end
end
+ return nil
+ end
- ary = [desc]
- if recurse == true or (recurse.is_a?(Integer) and recurse > -1)
- if ftype == "directory"
- children = Dir.entries(abspath)
- if ignore
- children = handleignore(children, abspath, ignore)
- end
- children.each { |child|
- next if child =~ /^\.\.?$/
- reclist(basepath, File.join(abspath, child), recurse, ignore).each { |cobj|
- ary << cobj
- }
- }
+ def reclist(abspath, recurse, ignore)
+ require 'puppet/file_serving'
+ require 'puppet/file_serving/fileset'
+ args = { :recurse => recurse, :links => :follow }
+ args[:ignore] = ignore if ignore
+ fs = Puppet::FileServing::Fileset.new(abspath, args)
+ ary = fs.files.collect do |file|
+ if file == "."
+ file = "/"
+ else
+ file = File.join("/", file )
end
+ stat = fs.stat(File.join(abspath, file))
+ next if stat.nil?
+ [ file, stat.ftype ]
end
return ary.compact
end
- # Deal with ignore parameters.
- def handleignore(files, path, ignore_patterns)
- ignore_patterns.each do |ignore|
- files.delete_if do |entry|
- File.fnmatch(ignore, entry, File::FNM_DOTMATCH)
- end
- end
- return files
- end
- end
+ end
# A special mount class specifically for the plugins mount -- just
# has some magic to effectively do a union mount of the 'plugins'
@@ -727,7 +712,7 @@ class Puppet::Network::Handler
end
def file_path(relpath, client = nil)
- mod = valid_modules.map { |m| mod_path_exists?(m, relpath, client) ? m : nil }.compact.first
+ return nil unless mod = valid_modules.map { |m| mod_path_exists?(m, relpath, client) ? m : nil }.compact.first
mod_file_path(mod, relpath, client)
end
@@ -735,9 +720,16 @@ class Puppet::Network::Handler
def list(relpath, recurse, ignore, client = nil)
result = []
valid_modules.each do |m|
- ary = reclist(mod_file_path(m, relpath, client), nil, recurse, ignore)
- ary = [] if ary.nil?
- result += ary
+ modpath = mod_file_path(m, relpath, client)
+ if FileTest.exists?(modpath)
+ if FileTest.directory?(modpath) and recurse
+ ary = reclist(modpath, recurse, ignore)
+ ary = [] if ary.nil?
+ result += ary
+ else
+ result += [["/", File.stat(modpath).ftype]]
+ end
+ end
end
result
end
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index 05ae7b9a2..71b633a09 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -24,7 +24,7 @@ class Puppet::Network::Handler
# Tell a client whether there's a fresh config for it
def freshness(client = nil, clientip = nil)
# Always force a recompile. Newer clients shouldn't do this (as of April 2008).
- return 0
+ return Time.now.to_i
end
def initialize(hash = {})
diff --git a/lib/puppet/network/http_server/rack.rb b/lib/puppet/network/http_server/rack.rb
new file mode 100644
index 000000000..806007a05
--- /dev/null
+++ b/lib/puppet/network/http_server/rack.rb
@@ -0,0 +1,148 @@
+# Author: Christian Hofstaedtler <hofstaedtler@inqnet.at>
+# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies,
+# 2008 Christian Hofstaedtler
+#
+# This file is mostly based on the mongrel module, which is part of
+# the standard puppet distribution.
+#
+# puppet/network/http_server/mongrel.rb has the following license,
+# and is based heavily on a file retrieved from:
+# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+require 'puppet'
+require 'puppet/network/handler'
+require 'puppet/sslcertificates'
+
+require 'xmlrpc/server'
+require 'puppet/network/xmlrpc/server'
+require 'puppet/network/http_server'
+require 'puppet/network/client_request'
+require 'puppet/network/handler'
+
+require 'resolv'
+require 'rack'
+
+# A handler for a Rack-style puppet(master)d. For the most part, it works
+# exactly the same as HTTPServer::Mongrel:
+# After checking whether the request itself is sane, the handler forwards
+# it to an internal instance of XMLRPC::BasicServer to process it.
+module Puppet::Network
+ class HTTPServer::Rack
+ attr_reader :xmlrpc_server
+
+ def initialize(handlers)
+ @debug = false
+ if Puppet[:debug]
+ @debug = true
+ end
+
+ Puppet.info "Starting Rack server for puppet version %s" % Puppet.version
+ if Puppet[:name] != "puppetmasterd" then
+ Puppet.warn 'Rack server is not named "puppetmasterd", this may be not what you want. ($0 = %s)' % $0
+ end
+
+ @xmlrpc_server = Puppet::Network::XMLRPCServer.new
+ handlers.each do |name, args|
+ unless handler = Puppet::Network::Handler.handler(name)
+ raise ArgumentError, "Invalid handler %s" % name
+ end
+ h = handler.new(args)
+ @xmlrpc_server.add_handler(handler.interface, h)
+ end
+ Puppet.info "Rack server is waiting to serve requests."
+ end
+
+ # Validate a rack-style request (in env), and run the requested XMLRPC
+ # call.
+ def process(env)
+ # time to serve a request
+ req = Rack::Request.new(env)
+
+ if @debug then
+ Puppet.info "Handling request, details:"
+ env.each do |name, val|
+ l = " env: %s ->" % name
+ l = l + ' %s' % val
+ Puppet.info l
+ end
+ end
+
+ if not req.post? then
+ return [405, { "Content-Type" => "text/html" }, "Method Not Allowed"]
+ end
+ if req.media_type() != "text/xml" then
+ return [400, { "Content-Type" => "text/html" }, "Bad Request"]
+ end
+ if req.content_length().to_i <= 0 then
+ return [411, { "Content-Type" => "text/html" }, "Length Required"]
+ end
+
+ body = ''
+ req.body().each { |line| body = body + line }
+ if @debug then
+ Puppet.info "Request Body: %s" % body
+ end
+ if body.size != req.content_length().to_i then
+ if @debug then
+ Puppet.info "body length didnt match %d" % body.size
+ Puppet.info " vs. -> %d" % req.content_length().to_i
+ end
+ return [400, { "Content-Type" => "text/html" }, "Bad Request Length"]
+ end
+ info = client_info(env)
+ begin
+ data = @xmlrpc_server.process(body, info)
+ return [200, { "Content-Type" => "text/xml; charset=utf-8" }, data]
+ rescue => detail
+ Puppet.err "Rack: Internal Server Error: XMLRPC_Server.process problem. Details follow: "
+ detail.backtrace.each { |line| Puppet.err " --> %s" % line }
+ return [500, { "Content-Type" => "text/html" }, "Internal Server Error"]
+ end
+ end
+
+ private
+
+ def client_info(request)
+ ip = request["REMOTE_ADDR"]
+ # JJM #906 The following dn.match regular expression is forgiving
+ # enough to match the two Distinguished Name string contents
+ # coming from Apache, Pound or other reverse SSL proxies.
+ if dn = request[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
+ client = dn_matchdata[1].to_str
+ valid = (request[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
+ else
+ begin
+ client = Resolv.getname(ip)
+ rescue => detail
+ Puppet.err "Could not resolve %s: %s" % [ip, detail]
+ client = "unknown"
+ end
+ valid = false
+ end
+ info = Puppet::Network::ClientRequest.new(client, ip, valid)
+ return info
+ end
+ end
+end
+
diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb
index e0fb5a0ab..c79f91d57 100644
--- a/lib/puppet/network/xmlrpc/client.rb
+++ b/lib/puppet/network/xmlrpc/client.rb
@@ -35,10 +35,6 @@ module Puppet::Network
interface.methods.each { |ary|
method = ary[0]
- if public_method_defined?(method)
- raise Puppet::DevError, "Method %s is already defined" %
- method
- end
newclient.send(:define_method,method) { |*args|
Puppet.debug "Calling %s.%s" % [namespace, method]
begin
@@ -51,7 +47,7 @@ module Puppet::Network
end
["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
if detail.message.include?(str)
- Puppet.warning "Certificate validation failed; considering using the certname configuration option"
+ Puppet.warning "Certificate validation failed; consider using the certname configuration option"
end
end
raise XMLRPCClientError,
@@ -74,6 +70,10 @@ module Puppet::Network
Puppet.warning "Other end went away; restarting connection and retrying"
self.recycle_connection
retry
+ rescue Timeout::Error => detail
+ Puppet.err "Connection timeout calling %s.%s: %s" %
+ [namespace, method, detail.to_s]
+ raise XMLRPCClientError.new("Connection Timeout").set_backtrace(detail.backtrace)
rescue => detail
if detail.message =~ /^Wrong size\. Was \d+, should be \d+$/
Puppet.warning "XMLRPC returned wrong size. Retrying."
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 341ec77ba..e10299d87 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -15,12 +15,7 @@ class Puppet::Node
attr_accessor :name, :classes, :parameters, :source, :ipaddress
attr_reader :time
-
- # Set the environment, making sure that it's valid.
- def environment=(value)
- raise(ArgumentError, "Invalid environment %s" % value) unless Puppet::Node::Environment.valid?(value)
- @environment = value
- end
+ attr_writer :environment
# Do not return environments that are the empty string, and use
# explicitly set environments, then facts, then a central env
@@ -28,7 +23,6 @@ class Puppet::Node
def environment
unless @environment
if env = parameters["environment"]
- raise(ArgumentError, "Invalid environment %s from parameters" % env) unless Puppet::Node::Environment.valid?(env)
@environment = env
else
@environment = Puppet::Node::Environment.new.name.to_s
diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb
index 343720a62..b64b9c2c4 100644
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@ -1,30 +1,14 @@
# Model the environment that a node can operate in. This class just
# provides a simple wrapper for the functionality around environments.
class Puppet::Node::Environment
- # Return the list of valid environments. Just looks them up in
- # the settings.
- def self.valid
- # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
- x = Puppet.settings.value(:environments).split(",").collect { |e| e.to_sym }
- end
-
- # Is the provided environment valid?
- def self.valid?(name)
- return false if name.to_s == ""
- valid.include?(name.to_sym)
- end
-
@seen = {}
- # Return an existing environment instance, or create a new one,
- # validating the environment name.
+ # Return an existing environment instance, or create a new one.
def self.new(name = nil)
name ||= Puppet.settings.value(:environment)
raise ArgumentError, "Environment name must be specified" unless name
- raise(ArgumentError, "'%s' is not a valid environment" % name) unless valid?(name)
-
symbol = name.to_sym
return @seen[symbol] if @seen[symbol]
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index c9bd7c9e8..ddf88521c 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -74,19 +74,25 @@ class Puppet::Parser::AST
end
# And include all of the AST subclasses.
+require 'puppet/parser/ast/arithmetic_operator'
require 'puppet/parser/ast/astarray'
require 'puppet/parser/ast/branch'
+require 'puppet/parser/ast/boolean_operator'
require 'puppet/parser/ast/caseopt'
require 'puppet/parser/ast/casestatement'
require 'puppet/parser/ast/collection'
require 'puppet/parser/ast/collexpr'
+require 'puppet/parser/ast/comparison_operator'
require 'puppet/parser/ast/definition'
require 'puppet/parser/ast/else'
require 'puppet/parser/ast/function'
require 'puppet/parser/ast/hostclass'
require 'puppet/parser/ast/ifstatement'
require 'puppet/parser/ast/leaf'
+require 'puppet/parser/ast/minus'
require 'puppet/parser/ast/node'
+require 'puppet/parser/ast/nop'
+require 'puppet/parser/ast/not'
require 'puppet/parser/ast/resource'
require 'puppet/parser/ast/resource_defaults'
require 'puppet/parser/ast/resource_override'
diff --git a/lib/puppet/parser/ast/arithmetic_operator.rb b/lib/puppet/parser/ast/arithmetic_operator.rb
new file mode 100644
index 000000000..8d9cef86a
--- /dev/null
+++ b/lib/puppet/parser/ast/arithmetic_operator.rb
@@ -0,0 +1,41 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+class Puppet::Parser::AST
+ class ArithmeticOperator < AST::Branch
+
+ attr_accessor :operator, :lval, :rval
+
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
+
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ lval = Puppet::Parser::Scope.number?(lval)
+ if lval == nil
+ raise ArgumentError, "left operand of %s is not a number" % @operator
+ end
+ rval = @rval.safeevaluate(scope)
+ rval = Puppet::Parser::Scope.number?(rval)
+ if rval == nil
+ raise ArgumentError, "right operand of %s is not a number" % @operator
+ end
+
+ # compute result
+ lval.send(@operator, rval)
+ end
+
+ def initialize(hash)
+ super
+
+ unless %w{+ - * / << >>}.include?(@operator)
+ raise ArgumentError, "Invalid arithmetic operator %s" % @operator
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/boolean_operator.rb b/lib/puppet/parser/ast/boolean_operator.rb
new file mode 100644
index 000000000..c3b5c7d41
--- /dev/null
+++ b/lib/puppet/parser/ast/boolean_operator.rb
@@ -0,0 +1,48 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+class Puppet::Parser::AST
+ class BooleanOperator < AST::Branch
+
+ attr_accessor :operator, :lval, :rval
+
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
+
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the first operand, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+
+ # return result
+ # lazy evaluate right operand
+ case @operator
+ 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";
+ if Puppet::Parser::Scope.true?(lval)
+ true
+ else
+ rval = @rval.safeevaluate(scope)
+ Puppet::Parser::Scope.true?(rval)
+ end
+ end
+ end
+
+ def initialize(hash)
+ super
+
+ unless %w{and or}.include?(@operator)
+ raise ArgumentError, "Invalid boolean operator %s" % @operator
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb
index 3e13d9400..baed325cb 100644
--- a/lib/puppet/parser/ast/collexpr.rb
+++ b/lib/puppet/parser/ast/collexpr.rb
@@ -30,7 +30,12 @@ class CollExpr < AST::Branch
case @oper
when "and": code1.call(resource) and code2.call(resource)
when "or": code1.call(resource) or code2.call(resource)
- when "==": resource[str1] == str2
+ when "==":
+ if resource[str1].is_a?(Array) && form != :exported
+ resource[str1].include?(str2)
+ else
+ resource[str1] == str2
+ end
when "!=": resource[str1] != str2
end
end
diff --git a/lib/puppet/parser/ast/comparison_operator.rb b/lib/puppet/parser/ast/comparison_operator.rb
new file mode 100644
index 000000000..63aa36c7f
--- /dev/null
+++ b/lib/puppet/parser/ast/comparison_operator.rb
@@ -0,0 +1,37 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+class Puppet::Parser::AST
+ class ComparisonOperator < AST::Branch
+
+ attr_accessor :operator, :lval, :rval
+
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
+
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ rval = @rval.safeevaluate(scope)
+
+ # return result
+ unless @operator == '!='
+ lval.send(@operator,rval)
+ else
+ lval != rval
+ end
+ end
+
+ def initialize(hash)
+ super
+
+ unless %w{== != < > <= >=}.include?(@operator)
+ raise ArgumentError, "Invalid comparison operator %s" % @operator
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/minus.rb b/lib/puppet/parser/ast/minus.rb
new file mode 100644
index 000000000..b0779a8ee
--- /dev/null
+++ b/lib/puppet/parser/ast/minus.rb
@@ -0,0 +1,23 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+# An object that returns a boolean which is the boolean not
+# of the given value.
+class Puppet::Parser::AST
+ class Minus < AST::Branch
+ attr_accessor :value
+
+ def each
+ yield @value
+ end
+
+ def evaluate(scope)
+ val = @value.safeevaluate(scope)
+ val = Puppet::Parser::Scope.number?(val)
+ if val == nil
+ raise ArgumentError, "minus operand %s is not a number" % val
+ end
+ return -val
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/nop.rb b/lib/puppet/parser/ast/nop.rb
new file mode 100644
index 000000000..ea5232043
--- /dev/null
+++ b/lib/puppet/parser/ast/nop.rb
@@ -0,0 +1,11 @@
+require 'puppet/parser/ast/branch'
+
+class Puppet::Parser::AST
+ # This class is a no-op, it doesn't produce anything
+ # when evaluated, hence it's name :-)
+ class Nop < AST::Leaf
+ def evaluate(scope)
+ # nothing to do
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/not.rb b/lib/puppet/parser/ast/not.rb
new file mode 100644
index 000000000..c8fa1df2c
--- /dev/null
+++ b/lib/puppet/parser/ast/not.rb
@@ -0,0 +1,19 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+# An object that returns a boolean which is the boolean not
+# of the given value.
+class Puppet::Parser::AST
+ class Not < AST::Branch
+ attr_accessor :value
+
+ def each
+ yield @value
+ end
+
+ def evaluate(scope)
+ val = @value.safeevaluate(scope)
+ return ! Puppet::Parser::Scope.true?(val)
+ end
+ end
+end
diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb
index f9464acda..8380dcd00 100644
--- a/lib/puppet/parser/ast/resource_override.rb
+++ b/lib/puppet/parser/ast/resource_override.rb
@@ -19,7 +19,7 @@ class Puppet::Parser::AST
# in the current scope.
def evaluate(scope)
# Get our object reference.
- object = @object.safeevaluate(scope)
+ resource = @object.safeevaluate(scope)
hash = {}
@@ -30,21 +30,28 @@ class Puppet::Parser::AST
# Now we just create a normal resource, but we call a very different
# method on the scope.
- obj = Puppet::Parser::Resource.new(
- :type => object.type,
- :title => object.title,
- :params => params,
- :file => @file,
- :line => @line,
- :source => scope.source,
- :scope => scope
- )
-
- # Now we tell the scope that it's an override, and it behaves as
- # necessary.
- scope.compiler.add_override(obj)
-
- obj
+ resource = [resource] unless resource.is_a?(Array)
+
+ resource = resource.collect do |r|
+ res = Puppet::Parser::Resource.new(
+ :type => r.type,
+ :title => r.title,
+ :params => params,
+ :file => @file,
+ :line => @line,
+ :source => scope.source,
+ :scope => scope
+ )
+
+ # Now we tell the scope that it's an override, and it behaves as
+ # necessary.
+ scope.compiler.add_override(res)
+
+ res
+ end
+ # decapsulate array in case of only one item
+ return resource.pop if resource.length == 1
+ return resource
end
# Create our ResourceDef. Handles type checking for us.
diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb
index 4bb41165a..e5e2dce99 100644
--- a/lib/puppet/parser/ast/resource_reference.rb
+++ b/lib/puppet/parser/ast/resource_reference.rb
@@ -24,16 +24,20 @@ class Puppet::Parser::AST
# and name.
def evaluate(scope)
title = @title.safeevaluate(scope)
+ title = [title] unless title.is_a?(Array)
+
if @type.to_s.downcase == "class"
- objtype = "class"
- title = qualified_class(scope, title)
+ resource_type = "class"
+ title = title.collect { |t| qualified_class(scope, t) }
else
- objtype = qualified_type(scope)
+ resource_type = qualified_type(scope)
end
- return Puppet::Parser::Resource::Reference.new(
- :type => objtype, :title => title
- )
+ title = title.collect { |t| Puppet::Parser::Resource::Reference.new(
+ :type => resource_type, :title => t
+ ) }
+ return title.pop if title.length == 1
+ return title
end
# Look up a fully qualified class name.
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index 07666acb4..7f07cc322 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -9,7 +9,19 @@ token FALSE EQUALS APPENDS LESSEQUAL NOTEQUAL DOT COLON LLCOLLECT RRCOLLECT
token QMARK LPAREN RPAREN ISEQUAL GREATEREQUAL GREATERTHAN LESSTHAN
token IF ELSE IMPORT DEFINE ELSIF VARIABLE CLASS INHERITS NODE BOOLEAN
token NAME SEMIC CASE DEFAULT AT LCOLLECT RCOLLECT CLASSNAME CLASSREF
-token NOT OR AND UNDEF PARROW
+token NOT OR AND UNDEF PARROW PLUS MINUS TIMES DIV LSHIFT RSHIFT UMINUS
+
+prechigh
+ right NOT
+ nonassoc UMINUS
+ left TIMES DIV
+ left MINUS PLUS
+ left LSHIFT RSHIFT
+ left NOTEQUAL ISEQUAL
+ left GREATEREQUAL GREATERTHAN LESSTHAN LESSEQUAL
+ left AND
+ left OR
+preclow
rule
program: statements {
@@ -283,7 +295,7 @@ resourcename: quotedtext
| variable
| array
-assignment: VARIABLE EQUALS rvalue {
+assignment: VARIABLE EQUALS expression {
if val[0] =~ /::/
raise Puppet::ParseError, "Cannot assign to variables in other namespaces"
end
@@ -292,7 +304,7 @@ assignment: VARIABLE EQUALS rvalue {
result = ast AST::VarDef, :name => variable, :value => val[2]
}
-append: VARIABLE APPENDS rvalue {
+append: VARIABLE APPENDS expression {
variable = ast AST::Name, :value => val[0]
result = ast AST::VarDef, :name => variable, :value => val[2], :append => true
}
@@ -388,14 +400,14 @@ boolean: BOOLEAN {
result = ast AST::Boolean, :value => val[0]
}
-resourceref: NAME LBRACK rvalue RBRACK {
+resourceref: NAME LBRACK rvalues RBRACK {
Puppet.warning addcontext("Deprecation notice: Resource references should now be capitalized")
result = ast AST::ResourceReference, :type => val[0], :title => val[2]
-} | classref LBRACK rvalue RBRACK {
+} | classref LBRACK rvalues RBRACK {
result = ast AST::ResourceReference, :type => val[0], :title => val[2]
}
-ifstatement: IF iftest LBRACE statements RBRACE else {
+ifstatement: IF expression LBRACE statements RBRACE else {
args = {
:test => val[1],
:statements => val[3]
@@ -407,15 +419,91 @@ ifstatement: IF iftest LBRACE statements RBRACE else {
result = ast AST::IfStatement, args
}
+ | IF expression LBRACE RBRACE else {
+ args = {
+ :test => val[1],
+ :statements => ast(AST::Nop)
+ }
+
+ if val[4]
+ args[:else] = val[4]
+ end
+
+ result = ast AST::IfStatement, args
+}
else: # nothing
| ELSE LBRACE statements RBRACE {
result = ast AST::Else, :statements => val[2]
}
+ | ELSE LBRACE RBRACE {
+ result = ast AST::Else, :statements => ast(AST::Nop)
+}
+
+# Unlike yacc/bison, it seems racc
+# gives tons of shift/reduce warnings
+# with the following syntax:
+#
+# expression: ...
+# | expression arithop expressio { ... }
+#
+# arithop: PLUS | MINUS | DIVIDE | TIMES ...
+#
+# So I had to develop the expression by adding one rule
+# per operator :-(
-# Currently we only support a single value, but eventually one assumes
-# we'll support operators and such.
-iftest: rvalue
+expression: rvalue
+ | expression PLUS expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression MINUS expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression DIV expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression TIMES expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression LSHIFT expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression RSHIFT expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | MINUS expression =UMINUS {
+ result = ast AST::Minus, :value => val[1]
+}
+ | expression NOTEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression ISEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression GREATERTHAN expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression GREATEREQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression LESSTHAN expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression LESSEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | NOT expression {
+ result = ast AST::Not, :value => val[1]
+}
+ | expression AND expression {
+ result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | expression OR expression {
+ result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+}
+ | LPAREN expression RPAREN {
+ result = val[1]
+}
casestatement: CASE rvalue LBRACE caseopts RBRACE {
options = val[3]
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 71210d919..9226434da 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -126,12 +126,22 @@ class Puppet::Parser::Lexer
'\\' => :BACKSLASH,
'=>' => :FARROW,
'+>' => :PARROW,
+ '+' => :PLUS,
+ '-' => :MINUS,
+ '/' => :DIV,
+ '*' => :TIMES,
+ '<<' => :LSHIFT,
+ '>>' => :RSHIFT,
%r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
%r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF
)
TOKENS.add_tokens "Whatever" => :DQTEXT, "Nomatter" => :SQTEXT, "alsonomatter" => :BOOLEAN
+ TOKENS.add_token :NUMBER, %r{\b(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b} do |lexer, value|
+ [TOKENS[:NAME], value]
+ end
+
TOKENS.add_token :NAME, %r{[a-z0-9][-\w]*} do |lexer, value|
string_token = self
# we're looking for keywords here
@@ -145,10 +155,6 @@ class Puppet::Parser::Lexer
[string_token, value]
end
- TOKENS.add_token :NUMBER, %r{[0-9]+} do |lexer, value|
- [TOKENS[:NAME], value]
- end
-
TOKENS.add_token :COMMENT, %r{#.*}, :skip => true
TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
@@ -432,6 +438,9 @@ class Puppet::Parser::Lexer
str.gsub!(/\\#{quote}/,quote)
end
+ # Add to our line count for every carriage return in multi-line strings.
+ @line += str.count("\n")
+
return str
end
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 69225cc2b..b025d52c5 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
@@ -29,7 +29,7 @@ module Puppet
class Parser < Racc::Parser
-module_eval <<'..end grammar.ra modeval..id7dbe8301d1', 'grammar.ra', 644
+module_eval <<'..end grammar.ra modeval..idf5ced460e1', 'grammar.ra', 732
# It got too annoying having code in a file that needs to be compiled.
require 'puppet/parser/parser_support'
@@ -41,524 +41,693 @@ require 'puppet/parser/parser_support'
# $Id$
-..end grammar.ra modeval..id7dbe8301d1
+..end grammar.ra modeval..idf5ced460e1
##### racc 1.4.5 generates ###
racc_reduce_table = [
0, 0, :racc_error,
- 1, 53, :_reduce_1,
- 1, 53, :_reduce_none,
- 1, 54, :_reduce_none,
- 2, 54, :_reduce_4,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 4, 64, :_reduce_18,
- 3, 64, :_reduce_19,
- 2, 64, :_reduce_20,
- 1, 70, :_reduce_none,
- 1, 70, :_reduce_none,
- 1, 71, :_reduce_none,
- 3, 71, :_reduce_24,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_none,
- 1, 73, :_reduce_32,
- 1, 72, :_reduce_none,
- 3, 72, :_reduce_34,
- 5, 57, :_reduce_35,
- 5, 57, :_reduce_36,
- 5, 57, :_reduce_37,
- 5, 68, :_reduce_38,
- 2, 58, :_reduce_39,
- 1, 89, :_reduce_40,
- 2, 89, :_reduce_41,
- 2, 59, :_reduce_42,
- 3, 90, :_reduce_43,
- 3, 90, :_reduce_44,
- 1, 91, :_reduce_none,
- 1, 91, :_reduce_none,
- 3, 91, :_reduce_47,
- 1, 92, :_reduce_none,
- 3, 92, :_reduce_49,
- 1, 93, :_reduce_none,
- 1, 93, :_reduce_none,
- 3, 94, :_reduce_52,
- 3, 94, :_reduce_53,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 4, 97, :_reduce_56,
- 1, 83, :_reduce_none,
- 3, 83, :_reduce_58,
- 0, 84, :_reduce_none,
- 1, 84, :_reduce_none,
- 1, 99, :_reduce_61,
- 1, 74, :_reduce_62,
- 1, 76, :_reduce_63,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
+ 1, 60, :_reduce_1,
+ 1, 60, :_reduce_none,
+ 1, 61, :_reduce_none,
+ 2, 61, :_reduce_4,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 4, 71, :_reduce_18,
+ 3, 71, :_reduce_19,
+ 2, 71, :_reduce_20,
+ 1, 77, :_reduce_none,
+ 1, 77, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 3, 78, :_reduce_24,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_32,
+ 1, 79, :_reduce_none,
+ 3, 79, :_reduce_34,
+ 5, 64, :_reduce_35,
+ 5, 64, :_reduce_36,
+ 5, 64, :_reduce_37,
+ 5, 75, :_reduce_38,
+ 2, 65, :_reduce_39,
+ 1, 96, :_reduce_40,
+ 2, 96, :_reduce_41,
+ 2, 66, :_reduce_42,
+ 3, 97, :_reduce_43,
+ 3, 97, :_reduce_44,
1, 98, :_reduce_none,
1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 3, 60, :_reduce_70,
- 3, 69, :_reduce_71,
- 0, 85, :_reduce_72,
- 1, 85, :_reduce_73,
- 3, 85, :_reduce_74,
- 3, 102, :_reduce_75,
- 3, 103, :_reduce_76,
- 1, 104, :_reduce_none,
- 1, 104, :_reduce_none,
- 0, 88, :_reduce_79,
- 1, 88, :_reduce_80,
- 3, 88, :_reduce_81,
+ 3, 98, :_reduce_47,
+ 1, 99, :_reduce_none,
+ 3, 99, :_reduce_49,
+ 1, 100, :_reduce_none,
+ 1, 100, :_reduce_none,
+ 3, 101, :_reduce_52,
+ 3, 101, :_reduce_53,
+ 1, 102, :_reduce_none,
+ 1, 102, :_reduce_none,
+ 4, 104, :_reduce_56,
+ 1, 90, :_reduce_none,
+ 3, 90, :_reduce_58,
+ 0, 91, :_reduce_none,
+ 1, 91, :_reduce_none,
+ 1, 106, :_reduce_61,
+ 1, 81, :_reduce_62,
+ 1, 83, :_reduce_63,
1, 105, :_reduce_none,
- 3, 105, :_reduce_83,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 4, 78, :_reduce_100,
- 3, 78, :_reduce_101,
- 1, 80, :_reduce_102,
- 1, 80, :_reduce_103,
- 1, 77, :_reduce_104,
- 4, 81, :_reduce_105,
- 4, 81, :_reduce_106,
- 6, 62, :_reduce_107,
- 0, 108, :_reduce_none,
- 4, 108, :_reduce_109,
- 1, 107, :_reduce_none,
- 5, 61, :_reduce_111,
- 1, 109, :_reduce_none,
- 2, 109, :_reduce_113,
- 5, 110, :_reduce_114,
- 4, 110, :_reduce_115,
- 1, 111, :_reduce_none,
- 3, 111, :_reduce_117,
- 3, 79, :_reduce_118,
- 1, 113, :_reduce_none,
- 4, 113, :_reduce_120,
- 1, 115, :_reduce_none,
- 3, 115, :_reduce_122,
- 3, 114, :_reduce_123,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
+ 1, 105, :_reduce_none,
+ 1, 105, :_reduce_none,
+ 1, 105, :_reduce_none,
+ 1, 105, :_reduce_none,
+ 1, 105, :_reduce_none,
+ 3, 67, :_reduce_70,
+ 3, 76, :_reduce_71,
+ 0, 92, :_reduce_72,
+ 1, 92, :_reduce_73,
+ 3, 92, :_reduce_74,
+ 3, 109, :_reduce_75,
+ 3, 111, :_reduce_76,
1, 112, :_reduce_none,
1, 112, :_reduce_none,
- 1, 112, :_reduce_131,
- 1, 116, :_reduce_132,
- 3, 116, :_reduce_133,
- 2, 63, :_reduce_134,
- 6, 65, :_reduce_135,
- 5, 65, :_reduce_136,
- 6, 66, :_reduce_137,
- 5, 66, :_reduce_138,
- 6, 67, :_reduce_139,
- 5, 67, :_reduce_140,
- 1, 87, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 119, :_reduce_none,
- 3, 119, :_reduce_145,
- 1, 121, :_reduce_none,
- 1, 121, :_reduce_none,
- 1, 121, :_reduce_none,
- 1, 121, :_reduce_none,
- 0, 55, :_reduce_150,
- 0, 122, :_reduce_151,
- 1, 117, :_reduce_none,
- 3, 117, :_reduce_153,
- 3, 117, :_reduce_154,
- 1, 123, :_reduce_none,
- 3, 123, :_reduce_156,
- 3, 124, :_reduce_157,
- 1, 124, :_reduce_158,
- 3, 124, :_reduce_159,
- 1, 124, :_reduce_160,
- 1, 120, :_reduce_none,
- 2, 120, :_reduce_162,
+ 0, 95, :_reduce_79,
+ 1, 95, :_reduce_80,
+ 3, 95, :_reduce_81,
+ 1, 113, :_reduce_none,
+ 3, 113, :_reduce_83,
+ 1, 103, :_reduce_none,
+ 1, 103, :_reduce_none,
+ 1, 103, :_reduce_none,
+ 1, 103, :_reduce_none,
+ 1, 103, :_reduce_none,
+ 1, 103, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 4, 85, :_reduce_100,
+ 3, 85, :_reduce_101,
+ 1, 87, :_reduce_102,
+ 1, 87, :_reduce_103,
+ 1, 84, :_reduce_104,
+ 4, 88, :_reduce_105,
+ 4, 88, :_reduce_106,
+ 6, 69, :_reduce_107,
+ 5, 69, :_reduce_108,
+ 0, 115, :_reduce_none,
+ 4, 115, :_reduce_110,
+ 3, 115, :_reduce_111,
+ 1, 108, :_reduce_none,
+ 3, 108, :_reduce_113,
+ 3, 108, :_reduce_114,
+ 3, 108, :_reduce_115,
+ 3, 108, :_reduce_116,
+ 3, 108, :_reduce_117,
+ 3, 108, :_reduce_118,
+ 2, 108, :_reduce_119,
+ 3, 108, :_reduce_120,
+ 3, 108, :_reduce_121,
+ 3, 108, :_reduce_122,
+ 3, 108, :_reduce_123,
+ 3, 108, :_reduce_124,
+ 3, 108, :_reduce_125,
+ 2, 108, :_reduce_126,
+ 3, 108, :_reduce_127,
+ 3, 108, :_reduce_128,
+ 3, 108, :_reduce_129,
+ 5, 68, :_reduce_130,
+ 1, 116, :_reduce_none,
+ 2, 116, :_reduce_132,
+ 5, 117, :_reduce_133,
+ 4, 117, :_reduce_134,
1, 118, :_reduce_none,
- 2, 118, :_reduce_164,
- 1, 125, :_reduce_none,
+ 3, 118, :_reduce_136,
+ 3, 86, :_reduce_137,
+ 1, 120, :_reduce_none,
+ 4, 120, :_reduce_139,
+ 1, 122, :_reduce_none,
+ 3, 122, :_reduce_141,
+ 3, 121, :_reduce_142,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_150,
+ 1, 123, :_reduce_151,
+ 3, 123, :_reduce_152,
+ 2, 70, :_reduce_153,
+ 6, 72, :_reduce_154,
+ 5, 72, :_reduce_155,
+ 6, 73, :_reduce_156,
+ 5, 73, :_reduce_157,
+ 6, 74, :_reduce_158,
+ 5, 74, :_reduce_159,
+ 1, 94, :_reduce_none,
+ 1, 89, :_reduce_none,
+ 1, 89, :_reduce_none,
+ 1, 126, :_reduce_none,
+ 3, 126, :_reduce_164,
+ 1, 128, :_reduce_none,
+ 1, 128, :_reduce_none,
+ 1, 128, :_reduce_none,
+ 1, 128, :_reduce_none,
+ 0, 62, :_reduce_169,
+ 0, 129, :_reduce_170,
+ 1, 124, :_reduce_none,
+ 3, 124, :_reduce_172,
+ 3, 124, :_reduce_173,
+ 1, 130, :_reduce_none,
+ 3, 130, :_reduce_175,
+ 3, 131, :_reduce_176,
+ 1, 131, :_reduce_177,
+ 3, 131, :_reduce_178,
+ 1, 131, :_reduce_179,
+ 1, 127, :_reduce_none,
+ 2, 127, :_reduce_181,
1, 125, :_reduce_none,
- 1, 75, :_reduce_167,
- 3, 100, :_reduce_168,
- 2, 100, :_reduce_169,
- 1, 106, :_reduce_none,
- 1, 106, :_reduce_none,
- 0, 86, :_reduce_none,
- 1, 86, :_reduce_173 ]
+ 2, 125, :_reduce_183,
+ 1, 132, :_reduce_none,
+ 1, 132, :_reduce_none,
+ 1, 82, :_reduce_186,
+ 3, 107, :_reduce_187,
+ 2, 107, :_reduce_188,
+ 1, 114, :_reduce_none,
+ 1, 114, :_reduce_none,
+ 0, 93, :_reduce_none,
+ 1, 93, :_reduce_192 ]
-racc_reduce_n = 174
+racc_reduce_n = 193
-racc_shift_n = 279
+racc_shift_n = 317
racc_action_table = [
- 77, 57, 60, 246, 167, 105, 77, 57, 60, 101,
- 199, 235, -124, 167, 241, 203, 77, 57, 60, 234,
- 54, 92, 77, 57, 60, 94, 131, 240, 208, 209,
- 104, 47, 77, 57, 60, 59, 63, 47, 95, 68,
- 131, 59, 63, 137, 55, 68, 166, 47, 65, 211,
- 55, 59, 178, 47, 65, 68, -125, 59, 63, 173,
- 116, 68, 96, 47, 65, -126, 55, 59, 119, -128,
- 65, 68, 77, 57, 60, 147, 116, 208, 209, 147,
- 65, 213, 77, 57, 60, 147, 47, 40, 41, 212,
- 47, 151, 54, 57, 60, 151, 47, 35, 77, 57,
- 60, 151, 188, 47, 4, 9, 172, 59, 63, 199,
- 9, 68, 50, 47, 203, -125, 55, 59, 63, 204,
- 65, 68, 42, 47, 205, 43, 55, 59, 63, 47,
- 65, 68, 35, 59, 63, 51, 55, 68, 167, 4,
- 65, 147, 55, 77, 57, 60, 65, 33, 34, 77,
- 57, 60, 47, 171, 40, 41, 35, 151, -127, 77,
- 57, 60, -129, 4, 214, 77, 57, 60, 208, 209,
- 40, 41, 57, 60, 47, 77, 57, 60, 59, 63,
- 47, 171, 68, -124, 59, 63, -130, 55, 68, 42,
- 47, 65, 43, 55, 59, 63, 47, 65, 68, -125,
- 59, 63, 219, 55, 68, 42, 47, 65, 43, 55,
- 59, 63, 111, 65, 68, 77, 57, 60, 92, 55,
- 191, 262, -127, 65, -124, 77, 57, 60, 135, 57,
- 60, 35, 57, 60, 159, 189, 224, 225, 4, 191,
- 192, 145, 57, 60, 145, 228, 47, 131, 57, 60,
- 59, 63, 127, 133, 68, 231, 47, 54, 132, 55,
- 59, 63, 47, 65, 68, -126, 59, 63, 168, 55,
- 68, -141, 47, 65, 51, 55, 59, 178, 47, 65,
- 68, 238, 59, 178, 239, 116, 68, 57, 60, 65,
- -126, 116, 242, 57, 60, 65, 129, 245, -128, 138,
- -129, 111, 94, 57, 60, -127, 171, 91, 165, 263,
- 265, 90, 163, 57, 60, 139, 140, 47, 46, 57,
- 60, 59, 178, 47, -129, 68, -126, 59, 178, 51,
- 116, 68, -124, 47, 65, -127, 116, 59, 178, 184,
- 65, 68, -125, 47, 57, 60, 116, 59, 178, 47,
- 65, 68, 45, 59, 63, 272, 116, 68, -173, 273,
- 65, 51, 55, 160, 57, 60, 65, 179, 143, 145,
- 183, 57, 60, nil, 47, 237, nil, nil, 59, 178,
- nil, nil, 68, nil, nil, nil, nil, 116, nil, nil,
- nil, 65, nil, nil, 47, nil, 278, nil, 59, 178,
- nil, 47, 68, nil, nil, 59, 178, 116, nil, 68,
- nil, 65, nil, nil, 116, 257, nil, 20, 65, 24,
- 26, nil, 1, 5, nil, 12, nil, 18, nil, 22,
- nil, 27, nil, nil, 4, 9, 20, 243, 24, 26,
- nil, 1, 5, nil, 12, nil, 18, nil, 22, nil,
- 27, nil, nil, 4, 9, nil, 270, nil, 20, nil,
- 24, 26, nil, 1, 5, nil, 12, nil, 18, nil,
- 22, nil, 27, nil, nil, 4, 9, 20, 233, 24,
- 26, nil, 1, 5, nil, 12, nil, 18, nil, 22,
- nil, 27, nil, nil, 4, 9, nil, 277, nil, 20,
- nil, 24, 26, nil, 1, 5, nil, 12, nil, 18,
- nil, 22, nil, 27, nil, nil, 4, 9, 20, 274,
- 24, 26, nil, 1, 5, nil, 12, nil, 18, nil,
- 22, nil, 27, nil, nil, 4, 9, nil, 217, nil,
- 20, nil, 24, 26, nil, 1, 5, nil, 12, nil,
- 18, nil, 22, nil, 27, nil, nil, 4, 9, 20,
- 215, 24, 26, nil, 1, 5, nil, 12, nil, 18,
- nil, 22, nil, 27, nil, nil, 4, 9, nil, 256,
- nil, 20, nil, 24, 26, nil, 1, 5, nil, 12,
- nil, 18, nil, 22, nil, 27, nil, nil, 4, 9,
- 20, nil, 24, 26, nil, 1, 5, nil, 12, nil,
- 18, nil, 22, nil, 27, nil, nil, 4, 9, 20,
- nil, 24, 26, nil, 1, 5, nil, 12, nil, 18,
- nil, 22, nil, 27, nil, nil, 4, 9, 20, nil,
- 24, 26, nil, 1, 5, nil, 12, nil, 18, nil,
- 22, nil, 27, nil, nil, 4, 9, 20, nil, 24,
- 26, nil, 1, 5, nil, 12, nil, 18, nil, 22,
- nil, 27, nil, nil, 4, 9, 20, nil, 24, 26,
- nil, 1, 5, nil, 12, nil, 18, nil, 22, nil,
- 27, nil, nil, 4, 9 ]
+ 75, 54, 57, 273, 178, 39, 40, 201, 88, 238,
+ 51, 178, 89, 213, 245, 8, 265, 198, 199, 246,
+ 72, 75, 54, 57, 136, 90, 39, 40, 236, 237,
+ 136, 45, 39, 40, 129, 56, 59, 236, 237, 66,
+ 41, 72, 154, 44, 52, 76, 177, 162, 62, 92,
+ 146, 84, 45, 75, 54, 57, 56, 59, 45, 126,
+ 66, 41, 250, 167, 44, 52, 76, 41, -146, 62,
+ 44, -143, 84, 72, 75, 54, 57, 291, 156, 157,
+ 158, 144, 145, 147, 45, 234, 253, 286, 56, 59,
+ 290, 162, 66, 233, 72, 285, 37, 52, 76, 158,
+ 144, 62, 45, 4, 84, 45, 154, 167, 37, 56,
+ 59, 155, 162, 66, 146, 4, 8, 37, 52, 76,
+ 150, 154, 62, 45, 4, 84, 158, 144, 167, 146,
+ 148, 151, 153, 105, 230, 75, 54, 57, 198, 199,
+ 33, 34, 156, 157, 158, 144, 145, 147, 156, 157,
+ 158, 144, 138, 149, 152, 72, 154, 156, 157, 158,
+ 144, 145, 147, 257, 146, 162, 45, 75, 54, 57,
+ 56, 59, 245, -145, 66, 37, 45, 246, 183, 52,
+ 76, 167, 4, 62, 54, 57, 84, 72, 75, 54,
+ 57, 259, 156, 157, 158, 144, 145, 147, 45, 161,
+ 239, 161, 56, 59, 236, 237, 66, 137, 72, 154,
+ 136, 52, 76, 198, 299, 62, -147, 146, 84, 45,
+ 75, 54, 57, 56, 59, 197, 51, 66, -144, 198,
+ 199, -148, 52, 76, 54, 57, 62, 268, 178, 84,
+ 72, 75, 54, 57, 188, 156, 157, 158, 144, 145,
+ 147, 45, -149, -144, 88, 56, 59, -146, -148, 66,
+ -143, 72, 135, -147, 52, 76, -160, 271, 62, -145,
+ 161, 84, 45, 75, 54, 57, 56, 59, 272, 172,
+ 66, 156, 157, 158, 144, 52, 76, 132, 173, 62,
+ 89, 108, 84, 72, 75, 54, 57, 156, 157, 158,
+ 144, 145, 147, 174, 45, 287, 288, 289, 56, 59,
+ 180, 105, 66, 100, 72, 188, 184, 52, 76, 186,
+ -143, 62, 271, 302, 84, 45, 75, 54, 57, 56,
+ 59, -143, -146, 66, -144, -148, -145, 303, 52, 76,
+ 188, -146, 62, 71, 193, 84, 72, 75, 54, 57,
+ 156, 157, 158, 144, 145, 147, 191, 45, 38, 310,
+ -192, 56, 59, -145, 35, 66, 189, 72, -144, nil,
+ 52, 76, nil, nil, 62, nil, nil, 84, 45, 75,
+ 54, 57, 56, 59, nil, nil, 66, nil, nil, nil,
+ nil, 52, 76, nil, nil, 62, nil, nil, 84, 72,
+ 75, 54, 57, nil, nil, nil, nil, nil, nil, nil,
+ 45, nil, nil, nil, 56, 59, nil, nil, 66, nil,
+ 72, nil, nil, 52, 76, nil, nil, 62, nil, nil,
+ 84, 45, 75, 54, 57, 56, 59, nil, nil, 66,
+ nil, nil, nil, nil, 52, 76, nil, nil, 62, nil,
+ nil, 84, 72, 75, 54, 57, nil, nil, nil, nil,
+ nil, nil, nil, 45, nil, nil, nil, 56, 59, nil,
+ nil, 66, nil, 72, nil, nil, 52, 76, nil, nil,
+ 62, nil, nil, 84, 45, 75, 54, 57, 56, 59,
+ nil, nil, 66, nil, nil, nil, nil, 52, 76, nil,
+ nil, 62, nil, nil, 84, 72, 75, 54, 57, nil,
+ nil, nil, nil, nil, nil, nil, 45, 75, 54, 57,
+ 56, 59, nil, nil, 66, nil, 72, nil, nil, 52,
+ 76, nil, nil, 62, nil, nil, 84, 45, 75, 54,
+ 57, 56, 59, nil, nil, 66, nil, nil, 45, nil,
+ 52, 76, 56, 116, 62, nil, 66, 84, 72, nil,
+ nil, 111, 75, 54, 57, 62, nil, nil, nil, 45,
+ nil, nil, nil, 56, 59, nil, nil, 66, 75, 54,
+ 57, 141, 52, 76, nil, nil, 62, nil, nil, 84,
+ nil, nil, nil, 45, 75, 54, 57, 56, 59, nil,
+ nil, 66, nil, nil, nil, nil, 52, nil, nil, 45,
+ 62, nil, nil, 56, 59, nil, nil, 66, 75, 54,
+ 57, nil, 52, nil, nil, 45, 62, nil, nil, 56,
+ 59, nil, nil, 66, 75, 54, 57, nil, 52, nil,
+ nil, nil, 62, nil, 75, 54, 57, nil, nil, 45,
+ 75, 54, 57, 56, 59, nil, nil, 66, nil, nil,
+ nil, nil, 52, nil, nil, 45, 62, nil, nil, 56,
+ 59, nil, nil, 66, nil, 45, nil, nil, 52, 56,
+ 195, 45, 62, 66, nil, 56, 59, nil, 111, 66,
+ nil, nil, 62, nil, 52, 75, 54, 57, 62, nil,
+ nil, 51, 54, 57, nil, nil, nil, nil, nil, nil,
+ nil, 75, 54, 57, nil, nil, nil, 75, 54, 57,
+ nil, 48, nil, nil, nil, nil, 45, 75, 54, 57,
+ 56, 59, 45, nil, 66, nil, 56, 59, nil, 52,
+ 66, nil, 45, 62, 49, 52, 56, 59, 45, 62,
+ 66, nil, 56, 59, nil, 52, 66, nil, 45, 62,
+ nil, 52, 56, 59, nil, 62, 66, 54, 57, 54,
+ 57, 52, nil, nil, nil, 62, nil, nil, nil, nil,
+ nil, nil, nil, 54, 57, 54, 57, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 45, nil, 45,
+ nil, 56, 195, 56, 195, 66, nil, 66, 54, 57,
+ 111, 49, 111, 45, 62, 45, 62, 56, 195, 56,
+ 195, 66, nil, 66, nil, nil, 111, nil, 111, nil,
+ 62, nil, 62, 54, 57, 54, 57, 284, 45, nil,
+ nil, nil, 56, 195, nil, nil, 66, nil, nil, 54,
+ 57, 111, 208, nil, nil, 62, 54, 57, nil, nil,
+ nil, nil, nil, 45, nil, 45, nil, 56, 195, 56,
+ 195, 66, nil, 66, nil, nil, 111, nil, 111, 45,
+ 62, nil, 62, 56, 195, nil, 45, 66, 54, 57,
+ 56, 195, 111, nil, 66, nil, 62, nil, nil, 111,
+ nil, nil, nil, 62, 54, 57, nil, nil, 131, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 45, nil,
+ nil, nil, 56, 59, 203, nil, 66, nil, nil, nil,
+ 49, 52, nil, nil, 45, 62, nil, nil, 56, 59,
+ nil, nil, 66, 150, 154, nil, 49, 52, nil, nil,
+ nil, 62, 146, 148, 151, 153, 150, 154, nil, nil,
+ nil, nil, nil, nil, 212, 146, 148, 151, 153, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 156, 157, 158, 144, 145, 147, nil, nil, nil, 149,
+ 152, 150, 154, 156, 157, 158, 144, 145, 147, nil,
+ 146, 148, 151, 153, 150, 154, nil, nil, nil, nil,
+ nil, nil, nil, 146, 148, 151, 153, nil, nil, nil,
+ nil, nil, nil, nil, 149, 152, nil, nil, 156, 157,
+ 158, 144, 145, 147, nil, nil, 296, nil, 152, 150,
+ 154, 156, 157, 158, 144, 145, 147, nil, 146, 148,
+ 151, 153, nil, nil, nil, nil, nil, 16, nil, 23,
+ 27, 294, 1, 5, nil, 10, nil, 13, nil, 20,
+ nil, 28, 149, 152, 4, 8, 156, 157, 158, 144,
+ 145, 147, 16, 293, 23, 27, nil, 1, 5, nil,
+ 10, nil, 13, nil, 20, nil, 28, nil, nil, 4,
+ 8, nil, 269, nil, 16, nil, 23, 27, nil, 1,
+ 5, nil, 10, nil, 13, nil, 20, nil, 28, nil,
+ nil, 4, 8, 16, 226, 23, 27, nil, 1, 5,
+ nil, 10, nil, 13, nil, 20, nil, 28, nil, nil,
+ 4, 8, nil, 308, nil, 16, nil, 23, 27, nil,
+ 1, 5, nil, 10, nil, 13, nil, 20, nil, 28,
+ nil, nil, 4, 8, 16, 312, 23, 27, nil, 1,
+ 5, nil, 10, nil, 13, nil, 20, nil, 28, nil,
+ nil, 4, 8, nil, 314, nil, 16, nil, 23, 27,
+ nil, 1, 5, nil, 10, nil, 13, nil, 20, nil,
+ 28, nil, nil, 4, 8, 16, 263, 23, 27, nil,
+ 1, 5, nil, 10, nil, 13, nil, 20, nil, 28,
+ nil, nil, 4, 8, nil, 315, nil, 16, nil, 23,
+ 27, nil, 1, 5, nil, 10, nil, 13, nil, 20,
+ nil, 28, nil, nil, 4, 8, 16, 256, 23, 27,
+ nil, 1, 5, nil, 10, nil, 13, nil, 20, nil,
+ 28, nil, nil, 4, 8, nil, 316, nil, 16, nil,
+ 23, 27, nil, 1, 5, nil, 10, nil, 13, nil,
+ 20, nil, 28, nil, nil, 4, 8, 16, nil, 23,
+ 27, nil, 1, 5, nil, 10, nil, 13, nil, 20,
+ nil, 28, nil, nil, 4, 8, 16, nil, 23, 27,
+ nil, 1, 5, nil, 10, nil, 13, nil, 20, nil,
+ 28, nil, nil, 4, 8, 16, nil, 23, 27, nil,
+ 1, 5, nil, 10, nil, 13, nil, 20, nil, 28,
+ nil, nil, 4, 8 ]
racc_action_check = [
- 228, 228, 228, 207, 111, 44, 54, 54, 54, 36,
- 241, 195, 83, 119, 201, 241, 168, 168, 168, 195,
- 63, 30, 92, 92, 92, 30, 119, 201, 207, 207,
- 44, 228, 46, 46, 46, 228, 228, 54, 30, 228,
- 63, 54, 54, 82, 228, 54, 111, 168, 228, 149,
- 54, 168, 168, 92, 54, 168, 85, 92, 92, 128,
- 168, 92, 30, 46, 168, 80, 92, 46, 46, 75,
- 92, 46, 167, 167, 167, 95, 46, 149, 149, 147,
- 46, 153, 166, 166, 166, 96, 95, 105, 105, 153,
- 147, 95, 18, 18, 18, 147, 96, 6, 20, 20,
- 20, 96, 133, 167, 6, 6, 126, 167, 167, 140,
- 133, 167, 18, 166, 140, 125, 167, 166, 166, 142,
- 167, 166, 105, 18, 144, 105, 166, 18, 18, 20,
- 166, 18, 5, 20, 20, 18, 18, 20, 145, 5,
- 18, 210, 20, 22, 22, 22, 20, 1, 1, 242,
- 242, 242, 210, 146, 12, 12, 26, 210, 123, 238,
- 238, 238, 74, 26, 156, 34, 34, 34, 156, 156,
- 104, 104, 139, 139, 22, 33, 33, 33, 22, 22,
- 242, 122, 22, 121, 242, 242, 73, 22, 242, 12,
- 238, 22, 12, 242, 238, 238, 34, 242, 238, 72,
- 34, 34, 164, 238, 34, 104, 33, 238, 104, 34,
- 33, 33, 165, 34, 33, 190, 190, 190, 71, 33,
- 230, 230, 70, 33, 69, 77, 77, 77, 77, 24,
- 24, 101, 50, 50, 101, 136, 169, 170, 101, 136,
- 136, 171, 235, 235, 172, 174, 190, 178, 138, 138,
- 190, 190, 50, 66, 190, 185, 77, 188, 64, 190,
- 77, 77, 50, 190, 77, 58, 50, 50, 120, 77,
- 50, 55, 235, 77, 50, 50, 235, 235, 138, 50,
- 235, 199, 138, 138, 200, 235, 138, 132, 132, 235,
- 118, 138, 203, 260, 260, 138, 53, 206, 52, 86,
- 49, 45, 38, 213, 213, 84, 227, 29, 107, 233,
- 234, 27, 106, 212, 212, 88, 89, 132, 17, 131,
- 131, 132, 132, 260, 248, 132, 250, 260, 260, 132,
- 132, 260, 251, 213, 132, 253, 260, 213, 213, 131,
- 260, 213, 254, 212, 179, 179, 213, 212, 212, 131,
- 213, 212, 15, 131, 131, 261, 212, 131, 262, 263,
- 212, 131, 131, 102, 129, 129, 131, 129, 91, 94,
- 130, 197, 197, nil, 179, 197, nil, nil, 179, 179,
- nil, nil, 179, nil, nil, nil, nil, 179, nil, nil,
- nil, 179, nil, nil, 129, nil, 276, nil, 129, 129,
- nil, 197, 129, nil, nil, 197, 197, 129, nil, 197,
- nil, 129, nil, nil, 197, 218, nil, 276, 197, 276,
- 276, nil, 276, 276, nil, 276, nil, 276, nil, 276,
- nil, 276, nil, nil, 276, 276, 218, 204, 218, 218,
- nil, 218, 218, nil, 218, nil, 218, nil, 218, nil,
- 218, nil, nil, 218, 218, nil, 244, nil, 204, nil,
- 204, 204, nil, 204, 204, nil, 204, nil, 204, nil,
- 204, nil, 204, nil, nil, 204, 204, 244, 193, 244,
- 244, nil, 244, 244, nil, 244, nil, 244, nil, 244,
- nil, 244, nil, nil, 244, 244, nil, 275, nil, 193,
- nil, 193, 193, nil, 193, 193, nil, 193, nil, 193,
- nil, 193, nil, 193, nil, nil, 193, 193, 275, 265,
- 275, 275, nil, 275, 275, nil, 275, nil, 275, nil,
- 275, nil, 275, nil, nil, 275, 275, nil, 163, nil,
- 265, nil, 265, 265, nil, 265, 265, nil, 265, nil,
- 265, nil, 265, nil, 265, nil, nil, 265, 265, 163,
- 160, 163, 163, nil, 163, 163, nil, 163, nil, 163,
- nil, 163, nil, 163, nil, nil, 163, 163, nil, 216,
- nil, 160, nil, 160, 160, nil, 160, 160, nil, 160,
- nil, 160, nil, 160, nil, 160, nil, nil, 160, 160,
- 216, nil, 216, 216, nil, 216, 216, nil, 216, nil,
- 216, nil, 216, nil, 216, nil, nil, 216, 216, 273,
- nil, 273, 273, nil, 273, 273, nil, 273, nil, 273,
- nil, 273, nil, 273, nil, nil, 273, 273, 32, nil,
- 32, 32, nil, 32, 32, nil, 32, nil, 32, nil,
- 32, nil, 32, nil, nil, 32, 32, 137, nil, 137,
- 137, nil, 137, 137, nil, 137, nil, 137, nil, 137,
- nil, 137, nil, nil, 137, 137, 0, nil, 0, 0,
+ 158, 158, 158, 232, 105, 129, 129, 135, 17, 170,
+ 59, 116, 17, 140, 174, 135, 202, 140, 140, 174,
+ 158, 84, 84, 84, 116, 17, 10, 10, 232, 232,
+ 59, 158, 126, 126, 42, 158, 158, 170, 170, 158,
+ 129, 84, 221, 129, 158, 158, 105, 162, 158, 17,
+ 221, 158, 84, 144, 144, 144, 84, 84, 162, 42,
+ 84, 10, 175, 162, 10, 84, 84, 126, 78, 84,
+ 126, 77, 84, 144, 145, 145, 145, 248, 221, 221,
+ 221, 221, 221, 221, 144, 165, 179, 242, 144, 144,
+ 248, 92, 144, 165, 145, 242, 5, 144, 144, 227,
+ 227, 144, 92, 5, 144, 145, 223, 92, 24, 145,
+ 145, 85, 90, 145, 223, 24, 24, 27, 145, 145,
+ 85, 85, 145, 90, 27, 145, 228, 228, 90, 85,
+ 85, 85, 85, 180, 159, 146, 146, 146, 159, 159,
+ 1, 1, 223, 223, 223, 223, 223, 223, 217, 217,
+ 217, 217, 71, 85, 85, 146, 218, 85, 85, 85,
+ 85, 85, 85, 185, 218, 235, 146, 157, 157, 157,
+ 146, 146, 291, 70, 146, 108, 235, 291, 108, 146,
+ 146, 235, 108, 146, 23, 23, 146, 157, 154, 154,
+ 154, 187, 218, 218, 218, 218, 218, 218, 157, 188,
+ 171, 189, 157, 157, 171, 171, 157, 68, 154, 220,
+ 195, 157, 157, 267, 267, 157, 67, 220, 157, 154,
+ 16, 16, 16, 154, 154, 134, 201, 154, 79, 134,
+ 134, 65, 154, 154, 173, 173, 154, 209, 161, 154,
+ 16, 147, 147, 147, 160, 220, 220, 220, 220, 220,
+ 220, 16, 80, 63, 61, 16, 16, 60, 81, 16,
+ 58, 147, 53, 82, 16, 16, 52, 226, 16, 87,
+ 89, 16, 147, 153, 153, 153, 147, 147, 231, 94,
+ 147, 215, 215, 215, 215, 147, 147, 50, 95, 147,
+ 97, 36, 147, 153, 152, 152, 152, 224, 224, 224,
+ 224, 224, 224, 99, 153, 245, 246, 247, 153, 153,
+ 106, 35, 153, 28, 152, 261, 109, 153, 153, 112,
+ 113, 153, 269, 271, 153, 152, 76, 76, 76, 152,
+ 152, 274, 276, 152, 277, 278, 280, 285, 152, 152,
+ 114, 115, 152, 15, 130, 152, 76, 151, 151, 151,
+ 216, 216, 216, 216, 216, 216, 127, 76, 6, 298,
+ 299, 76, 76, 125, 2, 76, 119, 151, 118, nil,
+ 76, 76, nil, nil, 76, nil, nil, 76, 151, 148,
+ 148, 148, 151, 151, nil, nil, 151, nil, nil, nil,
+ nil, 151, 151, nil, nil, 151, nil, nil, 151, 148,
+ 149, 149, 149, nil, nil, nil, nil, nil, nil, nil,
+ 148, nil, nil, nil, 148, 148, nil, nil, 148, nil,
+ 149, nil, nil, 148, 148, nil, nil, 148, nil, nil,
+ 148, 149, 72, 72, 72, 149, 149, nil, nil, 149,
+ nil, nil, nil, nil, 149, 149, nil, nil, 149, nil,
+ nil, 149, 72, 34, 34, 34, nil, nil, nil, nil,
+ nil, nil, nil, 72, nil, nil, nil, 72, 72, nil,
+ nil, 72, nil, 34, nil, nil, 72, 72, nil, nil,
+ 72, nil, nil, 72, 34, 150, 150, 150, 34, 34,
+ nil, nil, 34, nil, nil, nil, nil, 34, 34, nil,
+ nil, 34, nil, nil, 34, 150, 156, 156, 156, nil,
+ nil, nil, nil, nil, nil, nil, 150, 38, 38, 38,
+ 150, 150, nil, nil, 150, nil, 156, nil, nil, 150,
+ 150, nil, nil, 150, nil, nil, 150, 156, 33, 33,
+ 33, 156, 156, nil, nil, 156, nil, nil, 38, nil,
+ 156, 156, 38, 38, 156, nil, 38, 156, 33, nil,
+ nil, 38, 196, 196, 196, 38, nil, nil, nil, 33,
+ nil, nil, nil, 33, 33, nil, nil, 33, 75, 75,
+ 75, 75, 33, 33, nil, nil, 33, nil, nil, 33,
+ nil, nil, nil, 196, 51, 51, 51, 196, 196, nil,
+ nil, 196, nil, nil, nil, nil, 196, nil, nil, 75,
+ 196, nil, nil, 75, 75, nil, nil, 75, 268, 268,
+ 268, nil, 75, nil, nil, 51, 75, nil, nil, 51,
+ 51, nil, nil, 51, 20, 20, 20, nil, 51, nil,
+ nil, nil, 51, nil, 186, 186, 186, nil, nil, 268,
+ 287, 287, 287, 268, 268, nil, nil, 268, nil, nil,
+ nil, nil, 268, nil, nil, 20, 268, nil, nil, 20,
+ 20, nil, nil, 20, nil, 186, nil, nil, 20, 186,
+ 186, 287, 20, 186, nil, 287, 287, nil, 186, 287,
+ nil, nil, 186, nil, 287, 288, 288, 288, 287, nil,
+ nil, 13, 13, 13, nil, nil, nil, nil, nil, nil,
+ nil, 178, 178, 178, nil, nil, nil, 177, 177, 177,
+ nil, 13, nil, nil, nil, nil, 288, 88, 88, 88,
+ 288, 288, 13, nil, 288, nil, 13, 13, nil, 288,
+ 13, nil, 178, 288, 13, 13, 178, 178, 177, 13,
+ 178, nil, 177, 177, nil, 178, 177, nil, 88, 178,
+ nil, 177, 88, 88, nil, 177, 88, 208, 208, 132,
+ 132, 88, nil, nil, nil, 88, nil, nil, nil, nil,
+ nil, nil, nil, 233, 233, 234, 234, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 208, nil, 132,
+ nil, 208, 208, 132, 132, 208, nil, 132, 286, 286,
+ 208, 132, 132, 233, 208, 234, 132, 233, 233, 234,
+ 234, 233, nil, 234, nil, nil, 233, nil, 234, nil,
+ 233, nil, 234, 240, 240, 297, 297, 240, 286, nil,
+ nil, nil, 286, 286, nil, nil, 286, nil, nil, 137,
+ 137, 286, 137, nil, nil, 286, 172, 172, nil, nil,
+ nil, nil, nil, 240, nil, 297, nil, 240, 240, 297,
+ 297, 240, nil, 297, nil, nil, 240, nil, 297, 137,
+ 240, nil, 297, 137, 137, nil, 172, 137, 48, 48,
+ 172, 172, 137, nil, 172, nil, 137, nil, nil, 172,
+ nil, nil, nil, 172, 136, 136, nil, nil, 48, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 48, nil,
+ nil, nil, 48, 48, 136, nil, 48, nil, nil, nil,
+ 48, 48, nil, nil, 136, 48, nil, nil, 136, 136,
+ nil, nil, 136, 222, 222, nil, 136, 136, nil, nil,
+ nil, 136, 222, 222, 222, 222, 139, 139, nil, nil,
+ nil, nil, nil, nil, 139, 139, 139, 139, 139, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 222, 222, 222, 222, 222, 222, nil, nil, nil, 139,
+ 139, 102, 102, 139, 139, 139, 139, 139, 139, nil,
+ 102, 102, 102, 102, 219, 219, nil, nil, nil, nil,
+ nil, nil, nil, 219, 219, 219, 219, nil, nil, nil,
+ nil, nil, nil, nil, 102, 102, nil, nil, 102, 102,
+ 102, 102, 102, 102, nil, nil, 262, nil, 219, 101,
+ 101, 219, 219, 219, 219, 219, 219, nil, 101, 101,
+ 101, 101, nil, nil, nil, nil, nil, 262, nil, 262,
+ 262, 255, 262, 262, nil, 262, nil, 262, nil, 262,
+ nil, 262, 101, 101, 262, 262, 101, 101, 101, 101,
+ 101, 101, 255, 250, 255, 255, nil, 255, 255, nil,
+ 255, nil, 255, nil, 255, nil, 255, nil, nil, 255,
+ 255, nil, 225, nil, 250, nil, 250, 250, nil, 250,
+ 250, nil, 250, nil, 250, nil, 250, nil, 250, nil,
+ nil, 250, 250, 225, 155, 225, 225, nil, 225, 225,
+ nil, 225, nil, 225, nil, 225, nil, 225, nil, nil,
+ 225, 225, nil, 292, nil, 155, nil, 155, 155, nil,
+ 155, 155, nil, 155, nil, 155, nil, 155, nil, 155,
+ nil, nil, 155, 155, 292, 302, 292, 292, nil, 292,
+ 292, nil, 292, nil, 292, nil, 292, nil, 292, nil,
+ nil, 292, 292, nil, 303, nil, 302, nil, 302, 302,
+ nil, 302, 302, nil, 302, nil, 302, nil, 302, nil,
+ 302, nil, nil, 302, 302, 303, 191, 303, 303, nil,
+ 303, 303, nil, 303, nil, 303, nil, 303, nil, 303,
+ nil, nil, 303, 303, nil, 311, nil, 191, nil, 191,
+ 191, nil, 191, 191, nil, 191, nil, 191, nil, 191,
+ nil, 191, nil, nil, 191, 191, 311, 184, 311, 311,
+ nil, 311, 311, nil, 311, nil, 311, nil, 311, nil,
+ 311, nil, nil, 311, 311, nil, 313, nil, 184, nil,
+ 184, 184, nil, 184, 184, nil, 184, nil, 184, nil,
+ 184, nil, 184, nil, nil, 184, 184, 313, nil, 313,
+ 313, nil, 313, 313, nil, 313, nil, 313, nil, 313,
+ nil, 313, nil, nil, 313, 313, 0, nil, 0, 0,
nil, 0, 0, nil, 0, nil, 0, nil, 0, nil,
- 0, nil, nil, 0, 0 ]
+ 0, nil, nil, 0, 0, 19, nil, 19, 19, nil,
+ 19, 19, nil, 19, nil, 19, nil, 19, nil, 19,
+ nil, nil, 19, 19 ]
racc_action_pointer = [
- 648, 134, nil, nil, nil, 94, 59, nil, nil, nil,
- nil, nil, 151, nil, nil, 346, nil, 312, 90, nil,
- 96, nil, 141, nil, 226, nil, 118, 269, nil, 307,
- 19, nil, 610, 173, 163, nil, -26, nil, 296, nil,
- nil, nil, nil, nil, -5, 263, 30, nil, nil, 279,
- 229, nil, 277, 275, 4, 269, nil, nil, 244, nil,
- nil, nil, nil, 18, 248, nil, 243, nil, nil, 203,
- 201, 216, 178, 165, 141, 48, nil, 223, nil, nil,
- 44, nil, 37, -9, 284, 35, 293, nil, 305, 294,
- nil, 368, 20, nil, 331, 53, 63, nil, nil, nil,
- nil, 193, 357, nil, 167, 84, 306, 298, nil, nil,
- nil, -5, nil, nil, nil, nil, nil, nil, 269, 4,
- 229, 162, 171, 137, nil, 94, 88, nil, 36, 361,
- 365, 316, 284, 64, nil, nil, 230, 629, 245, 169,
- 76, nil, 113, nil, 119, 129, 143, 57, nil, 29,
- nil, nil, nil, 65, nil, nil, 120, nil, nil, nil,
- 553, nil, nil, 531, 195, 174, 80, 70, 14, 229,
- 230, 203, 206, nil, 236, nil, nil, nil, 225, 341,
- nil, nil, nil, nil, nil, 232, nil, nil, 255, nil,
- 213, nil, nil, 471, nil, 1, nil, 368, nil, 268,
- 261, 4, nil, 279, 430, nil, 290, -20, nil, nil,
- 119, nil, 310, 300, nil, nil, 572, nil, 408, nil,
- nil, nil, nil, nil, nil, nil, nil, 296, -2, nil,
- 211, nil, nil, 280, 304, 239, nil, nil, 157, nil,
- nil, -23, 147, nil, 449, nil, nil, nil, 303, nil,
- 305, 311, nil, 314, 321, nil, nil, nil, nil, nil,
- 290, 348, 351, 353, nil, 512, nil, nil, nil, nil,
- nil, nil, nil, 591, nil, 490, 389, nil, nil ]
+ 1278, 127, 358, nil, nil, 58, 352, nil, nil, nil,
+ 23, nil, nil, 699, nil, 343, 218, 6, nil, 1297,
+ 632, nil, nil, 181, 70, nil, nil, 79, 271, nil,
+ nil, nil, nil, 536, 451, 273, 256, nil, 515, nil,
+ nil, nil, 24, nil, nil, nil, nil, nil, 885, nil,
+ 277, 592, 264, 252, nil, nil, nil, nil, 239, 8,
+ 236, 252, nil, 232, nil, 210, nil, 195, 186, nil,
+ 152, 152, 430, nil, nil, 576, 324, 50, 47, 207,
+ 231, 237, 242, nil, 19, 105, nil, 248, 725, 232,
+ 90, nil, 69, nil, 273, 278, nil, 284, nil, 281,
+ nil, 1024, 976, nil, nil, -5, 300, nil, 137, 310,
+ nil, nil, 280, 299, 330, 320, 2, nil, 347, 348,
+ nil, nil, nil, nil, nil, 342, 29, 350, nil, 2,
+ 321, nil, 766, nil, 220, -31, 901, 846, nil, 941,
+ 8, nil, nil, nil, 51, 72, 133, 239, 377, 398,
+ 483, 345, 292, 271, 186, 1117, 504, 165, -2, 129,
+ 234, 229, 25, nil, nil, 69, nil, nil, nil, nil,
+ -11, 156, 853, 231, -19, 56, nil, 715, 709, 79,
+ 95, nil, nil, nil, 1240, 156, 642, 184, 161, 163,
+ nil, 1199, nil, nil, nil, 188, 560, nil, nil, nil,
+ nil, 224, -7, nil, nil, nil, nil, nil, 764, 228,
+ nil, nil, nil, nil, nil, 229, 298, 96, 140, 989,
+ 193, 26, 928, 90, 245, 1095, 238, 45, 72, nil,
+ nil, 271, -20, 780, 782, 143, nil, nil, nil, nil,
+ 830, nil, 77, nil, nil, 292, 293, 284, 67, nil,
+ 1076, nil, nil, nil, nil, 1054, nil, nil, nil, nil,
+ nil, 305, 1029, nil, nil, nil, nil, 204, 616, 293,
+ nil, 317, nil, nil, 310, nil, 311, 313, 314, nil,
+ 315, nil, nil, nil, nil, 331, 805, 648, 693, nil,
+ nil, 139, 1136, nil, nil, nil, nil, 832, 352, 353,
+ nil, nil, 1158, 1177, nil, nil, nil, nil, nil, nil,
+ nil, 1218, nil, 1259, nil, nil, nil ]
racc_action_default = [
- -150, -174, -14, -2, -143, -174, -174, -15, -3, -141,
- -16, -5, -174, -17, -6, -174, -7, -174, -142, -8,
- -174, -9, -174, -10, -174, -11, -174, -40, -12, -174,
- -174, -13, -1, -174, -174, -142, -150, -39, -174, -144,
- -148, -147, -146, -149, -150, -79, -72, -167, -130, -28,
- -174, -32, -29, -174, -174, -63, -30, -102, -31, -104,
- -103, -33, -20, -62, -21, -61, -22, -23, -131, -25,
- -26, -174, -27, -99, -93, -98, -96, -174, -110, -94,
- -90, -97, -174, -91, -95, -92, -174, -132, -134, -150,
- -41, -174, -174, -42, -72, -150, -150, -4, -70, -71,
- -163, -174, -174, -161, -174, -174, -174, -172, -77, -78,
- -80, -174, -129, -128, -69, -67, -63, -73, -64, -62,
- -59, -65, -172, -68, -57, -66, -174, -19, -174, -174,
- -174, -174, -174, -174, -82, -169, -174, -174, -174, -174,
- -151, -152, -174, 279, -174, -174, -172, -150, -45, -174,
- -46, -62, -48, -174, -55, -54, -174, -164, -165, -166,
- -174, -162, -145, -174, -174, -173, -174, -174, -60, -174,
- -174, -173, -72, -18, -174, -126, -118, -119, -62, -174,
- -124, -127, -125, -105, -101, -174, -24, -34, -174, -168,
- -174, -170, -171, -174, -112, -174, -116, -174, -133, -160,
- -174, -174, -155, -158, -174, -106, -174, -174, -51, -50,
- -174, -44, -174, -174, -43, -138, -174, -140, -174, -38,
- -81, -76, -75, -58, -35, -36, -74, -172, -174, -121,
- -172, -100, -83, -108, -174, -174, -113, -111, -174, -153,
- -154, -174, -174, -136, -174, -37, -49, -47, -87, -88,
- -84, -85, -52, -89, -86, -53, -137, -139, -56, -123,
- -174, -174, -171, -174, -107, -174, -117, -159, -156, -157,
- -135, -122, -120, -174, -115, -174, -174, -114, -109 ]
+ -169, -193, -193, -7, -162, -193, -193, -8, -160, -9,
+ -193, -10, -11, -161, -12, -193, -193, -193, -13, -1,
+ -193, -14, -2, -193, -193, -15, -3, -193, -40, -16,
+ -5, -17, -6, -193, -193, -79, -169, -161, -72, -167,
+ -166, -165, -169, -163, -168, -186, -33, -20, -193, -32,
+ -21, -193, -63, -22, -102, -23, -104, -103, -25, -62,
+ -26, -193, -61, -27, -149, -28, -150, -29, -193, -30,
+ -31, -193, -193, -112, -97, -193, -193, -91, -95, -92,
+ -99, -93, -98, -96, -193, -193, -94, -90, -193, -72,
+ -169, -42, -169, -4, -193, -153, -151, -193, -39, -169,
+ -41, -70, -71, -78, -80, -193, -191, -77, -193, -193,
+ -182, -63, -59, -65, -191, -68, -62, -57, -66, -193,
+ -148, -147, -69, -67, -73, -64, -193, -193, -180, -193,
+ -193, -19, -193, -82, -193, -193, -193, -193, 317, -193,
+ -193, -188, -126, -119, -193, -193, -193, -193, -193, -193,
+ -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+ -191, -193, -169, -46, -48, -193, -55, -62, -54, -45,
+ -193, -193, -193, -193, -170, -193, -171, -193, -193, -193,
+ -192, -183, -184, -185, -193, -193, -60, -193, -192, -72,
+ -181, -193, -164, -18, -24, -62, -193, -105, -189, -190,
+ -34, -193, -193, -101, -138, -143, -146, -144, -193, -193,
+ -145, -137, -129, -187, -115, -117, -121, -118, -123, -128,
+ -125, -122, -127, -124, -120, -193, -109, -113, -114, -116,
+ -106, -193, -193, -193, -193, -193, -51, -50, -44, -43,
+ -193, -131, -193, -135, -152, -179, -177, -193, -193, -174,
+ -193, -76, -75, -38, -81, -193, -157, -35, -58, -36,
+ -74, -191, -193, -159, -83, -100, -140, -191, -193, -109,
+ -108, -193, -37, -49, -85, -52, -89, -86, -87, -88,
+ -84, -53, -47, -132, -130, -193, -193, -193, -193, -172,
+ -173, -193, -193, -155, -156, -56, -158, -193, -193, -190,
+ -142, -107, -193, -193, -136, -178, -176, -175, -154, -141,
+ -139, -193, -111, -193, -134, -110, -133 ]
racc_goto_table = [
- 30, 32, 56, 108, 174, 97, 38, 110, 52, 39,
- 122, 177, 62, 196, 190, 3, 202, 114, 194, 29,
- 58, 124, 149, 156, 164, 247, 87, 136, 36, 93,
- 115, 82, 30, 264, 56, 197, 113, 252, 255, 170,
- 52, 107, 169, 176, 128, 120, 230, 88, 118, 89,
- 142, 100, 58, 102, 174, 44, 106, 186, 146, 103,
- 49, 229, 200, 206, 201, 37, 157, nil, nil, nil,
- nil, 61, 196, 81, 207, 81, nil, 236, nil, nil,
- nil, nil, nil, nil, nil, nil, 81, 81, 112, nil,
- nil, nil, 49, nil, nil, nil, nil, nil, nil, nil,
- nil, 161, 162, 61, 141, nil, nil, 81, 260, nil,
- 266, nil, nil, nil, nil, 56, 56, 268, 72, 113,
- nil, 52, 52, 108, 158, 185, nil, 220, 113, 226,
- 81, 175, nil, 58, 58, 174, 227, 30, 193, 114,
- 175, 198, 271, 223, 258, 81, 125, 261, nil, nil,
- 72, nil, 115, nil, nil, nil, nil, nil, 113, nil,
- 30, 216, nil, 30, 218, nil, 97, nil, nil, 113,
- 118, 112, nil, 49, 49, nil, nil, nil, nil, 70,
- 112, 175, nil, nil, 61, nil, 187, 113, nil, 97,
- nil, 97, nil, 30, nil, nil, 249, 249, nil, 175,
- nil, nil, 113, 113, 30, 244, nil, 123, nil, nil,
- 112, 70, nil, nil, 250, 250, 30, 97, 30, 81,
- 81, 112, nil, nil, nil, 113, nil, nil, nil, 182,
- nil, 72, 72, nil, nil, nil, nil, 175, 182, 112,
- nil, nil, nil, 81, 30, nil, nil, nil, 97, 97,
- 113, nil, nil, nil, 248, 248, 155, 155, nil, nil,
- nil, nil, 175, nil, nil, 30, 275, nil, 125, 78,
- nil, 86, 69, 30, 276, 30, 30, 112, nil, 182,
- nil, 81, 98, 99, nil, nil, nil, nil, nil, nil,
- 181, 81, 70, 70, nil, 81, nil, 182, nil, 181,
- 121, nil, 112, 130, 69, nil, nil, nil, 155, 73,
- nil, 73, 254, 254, nil, nil, nil, nil, nil, nil,
- nil, nil, 73, 73, nil, nil, 134, nil, nil, 123,
- nil, nil, nil, nil, nil, 182, nil, nil, nil, nil,
- 181, 144, nil, 73, nil, nil, nil, nil, nil, 154,
- 154, nil, nil, nil, nil, nil, nil, nil, 181, nil,
- 182, nil, nil, nil, nil, nil, 73, nil, nil, nil,
- nil, 155, nil, 253, 253, nil, nil, nil, nil, nil,
- nil, 73, nil, 180, nil, 69, 69, nil, nil, nil,
- nil, nil, 180, nil, nil, nil, 181, nil, nil, nil,
- nil, 154, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 221, 222, nil, nil, nil,
- nil, 181, 121, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 180, nil, nil, nil, nil, nil, 232,
+ 2, 179, 93, 17, 209, 43, 19, 204, 47, 187,
+ 249, 122, 104, 46, 36, 70, 22, 114, 107, 2,
+ 241, 170, 17, 171, 117, 96, 270, 97, 15, 134,
+ 275, 281, 282, 297, 91, 240, 99, 106, 185, 243,
+ 125, 211, 112, 130, 267, 95, 64, 175, 46, 109,
+ 70, 42, 110, 140, 127, 231, 194, 247, 128, 67,
+ 248, 98, 181, nil, nil, nil, 159, nil, 160, 301,
+ 69, 64, nil, nil, nil, 209, nil, nil, 266, nil,
+ nil, 64, nil, nil, 121, nil, nil, nil, 283, nil,
+ nil, nil, nil, 232, 67, 123, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 69, nil, 243, nil, nil,
+ nil, 94, nil, nil, nil, 176, nil, 182, nil, nil,
+ nil, 190, nil, nil, 192, 65, nil, 307, nil, nil,
+ nil, 202, nil, nil, 70, 200, 46, nil, 70, 210,
+ nil, nil, 133, nil, nil, nil, nil, nil, nil, nil,
+ 120, nil, nil, 304, nil, 2, 295, 254, 17, 122,
+ 65, 225, 298, 107, 209, 64, 133, 309, 261, 64,
+ 64, 260, 258, nil, 210, 244, nil, nil, 67, 133,
+ nil, nil, 67, 121, 2, nil, nil, 17, 125, 69,
+ 255, 2, nil, 69, 17, nil, nil, 262, nil, 60,
+ nil, nil, 63, nil, nil, 64, nil, nil, 93, nil,
+ 210, nil, nil, nil, nil, nil, nil, nil, 121, 64,
+ nil, nil, nil, nil, 115, 2, nil, 118, 17, nil,
+ nil, nil, 121, nil, 60, 280, 280, 63, 93, nil,
+ nil, 64, 210, 123, 65, 93, nil, nil, 65, 120,
+ 2, nil, nil, 17, 121, 2, 292, nil, 17, nil,
+ nil, nil, 2, nil, nil, 17, 64, 64, 251, 252,
+ nil, nil, nil, 64, nil, 93, 168, nil, 168, 121,
+ 121, nil, nil, nil, 120, nil, 121, 264, 210, nil,
+ 279, 279, 2, nil, 93, 17, 93, nil, 120, 210,
+ nil, nil, 2, 2, nil, 17, 17, nil, 311, 313,
+ nil, 2, 58, 2, 17, nil, 17, 85, 60, 64,
+ 120, 63, 60, 206, nil, 63, 207, nil, nil, nil,
+ 64, nil, 121, nil, 101, 102, nil, 113, nil, nil,
+ nil, nil, nil, 121, nil, 278, 278, 58, 168, nil,
+ nil, nil, 120, nil, nil, nil, nil, nil, 206, 300,
+ nil, 207, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 115, 139, nil, 118, nil, 142, 305, 306,
+ nil, nil, nil, nil, nil, 143, nil, nil, nil, 166,
+ nil, 166, nil, nil, 206, nil, nil, 207, 120, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 120,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 276,
+ 276, 168, 277, 277, nil, nil, 206, nil, nil, 207,
+ nil, 58, nil, nil, nil, 58, 205, nil, nil, nil,
+ nil, nil, nil, nil, nil, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, nil, 227, 228, 229,
+ nil, 166, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, 205, 206, nil, nil, 207, nil, nil, nil, nil,
+ nil, nil, nil, 206, nil, 113, 207, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 205, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 180, nil, nil, nil, 73, 73, nil, nil, nil,
- nil, nil, nil, nil, 154, nil, 251, 251, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 259, nil, 73,
- nil, nil, nil, nil, nil, nil, nil, 267, nil, 180,
- nil, 269, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 274, 274, 166, nil, nil, nil, nil, 205,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 180, nil, nil, 73, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 73, nil, nil,
- nil, 73 ]
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 205, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 205 ]
racc_goto_check = [
- 35, 2, 27, 50, 60, 4, 35, 52, 26, 69,
- 33, 62, 18, 60, 54, 3, 72, 48, 58, 1,
- 28, 45, 39, 39, 34, 40, 28, 53, 30, 38,
- 27, 55, 35, 56, 27, 57, 26, 44, 44, 34,
- 26, 36, 32, 61, 18, 31, 63, 64, 28, 30,
- 65, 3, 28, 66, 60, 67, 68, 21, 33, 3,
- 25, 62, 70, 34, 71, 5, 73, nil, nil, nil,
- nil, 29, 60, 29, 39, 29, nil, 58, nil, nil,
- nil, nil, nil, nil, nil, nil, 29, 29, 25, nil,
- nil, nil, 25, nil, nil, nil, nil, nil, nil, nil,
- nil, 69, 69, 29, 3, nil, nil, 29, 54, nil,
- 60, nil, nil, nil, nil, 27, 27, 72, 24, 26,
- nil, 26, 26, 50, 30, 18, nil, 52, 26, 50,
- 29, 28, nil, 28, 28, 60, 33, 35, 2, 48,
- 28, 28, 62, 45, 34, 29, 24, 34, nil, nil,
- 24, nil, 27, nil, nil, nil, nil, nil, 26, nil,
- 35, 2, nil, 35, 2, nil, 4, nil, nil, 26,
- 28, 25, nil, 25, 25, nil, nil, nil, nil, 23,
- 25, 28, nil, nil, 29, nil, 29, 26, nil, 4,
- nil, 4, nil, 35, nil, nil, 27, 27, nil, 28,
- nil, nil, 26, 26, 35, 2, nil, 23, nil, nil,
- 25, 23, nil, nil, 28, 28, 35, 4, 35, 29,
- 29, 25, nil, nil, nil, 26, nil, nil, nil, 24,
- nil, 24, 24, nil, nil, nil, nil, 28, 24, 25,
- nil, nil, nil, 29, 35, nil, nil, nil, 4, 4,
- 26, nil, nil, nil, 25, 25, 23, 23, nil, nil,
- nil, nil, 28, nil, nil, 35, 2, nil, 24, 49,
- nil, 49, 22, 35, 2, 35, 35, 25, nil, 24,
- nil, 29, 49, 49, nil, nil, nil, nil, nil, nil,
- 23, 29, 23, 23, nil, 29, nil, 24, nil, 23,
- 22, nil, 25, 49, 22, nil, nil, nil, 23, 47,
- nil, 47, 24, 24, nil, nil, nil, nil, nil, nil,
- nil, nil, 47, 47, nil, nil, 49, nil, nil, 23,
- nil, nil, nil, nil, nil, 24, nil, nil, nil, nil,
- 23, 49, nil, 47, nil, nil, nil, nil, nil, 22,
- 22, nil, nil, nil, nil, nil, nil, nil, 23, nil,
- 24, nil, nil, nil, nil, nil, 47, nil, nil, nil,
- nil, 23, nil, 23, 23, nil, nil, nil, nil, nil,
- nil, 47, nil, 22, nil, 22, 22, nil, nil, nil,
- nil, nil, 22, nil, nil, nil, 23, nil, nil, nil,
+ 29, 34, 4, 35, 60, 69, 2, 62, 18, 34,
+ 72, 48, 53, 29, 30, 28, 3, 33, 50, 29,
+ 58, 39, 35, 39, 45, 28, 56, 35, 1, 54,
+ 44, 44, 40, 55, 38, 57, 30, 36, 32, 60,
+ 28, 61, 31, 18, 63, 64, 47, 65, 29, 66,
+ 28, 67, 3, 54, 68, 34, 21, 70, 3, 26,
+ 71, 5, 73, nil, nil, nil, 54, nil, 33, 56,
+ 27, 47, nil, nil, nil, 60, nil, nil, 62, nil,
+ nil, 47, nil, nil, 26, nil, nil, nil, 58, nil,
+ nil, nil, nil, 39, 26, 27, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 27, nil, 60, nil, nil,
+ nil, 51, nil, nil, nil, 3, nil, 30, nil, nil,
+ nil, 69, nil, nil, 69, 25, nil, 72, nil, nil,
+ nil, 18, nil, nil, 28, 29, 29, nil, 28, 28,
+ nil, nil, 51, nil, nil, nil, nil, nil, nil, nil,
+ 25, nil, nil, 60, nil, 29, 34, 53, 35, 48,
+ 25, 2, 34, 50, 60, 47, 51, 62, 33, 47,
+ 47, 50, 45, nil, 28, 28, nil, nil, 26, 51,
+ nil, nil, 26, 26, 29, nil, nil, 35, 28, 27,
+ 2, 29, nil, 27, 35, nil, nil, 2, nil, 23,
+ nil, nil, 24, nil, nil, 47, nil, nil, 4, nil,
+ 28, nil, nil, nil, nil, nil, nil, nil, 26, 47,
+ nil, nil, nil, nil, 23, 29, nil, 24, 35, nil,
+ nil, nil, 26, nil, 23, 28, 28, 24, 4, nil,
+ nil, 47, 28, 27, 25, 4, nil, nil, 25, 25,
+ 29, nil, nil, 35, 26, 29, 2, nil, 35, nil,
+ nil, nil, 29, nil, nil, 35, 47, 47, 51, 51,
+ nil, nil, nil, 47, nil, 4, 23, nil, 23, 26,
+ 26, nil, nil, nil, 25, nil, 26, 51, 28, nil,
+ 27, 27, 29, nil, 4, 35, 4, nil, 25, 28,
+ nil, nil, 29, 29, nil, 35, 35, nil, 2, 2,
+ nil, 29, 22, 29, 35, nil, 35, 49, 23, 47,
+ 25, 24, 23, 23, nil, 24, 24, nil, nil, nil,
+ 47, nil, 26, nil, 49, 49, nil, 22, nil, nil,
+ nil, nil, nil, 26, nil, 25, 25, 22, 23, nil,
+ nil, nil, 25, nil, nil, nil, nil, nil, 23, 51,
+ nil, 24, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 23, 49, nil, 24, nil, 49, 51, 51,
+ nil, nil, nil, nil, nil, 49, nil, nil, nil, 22,
+ nil, 22, nil, nil, 23, nil, nil, 24, 25, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 25,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 23,
+ 23, 23, 24, 24, nil, nil, 23, nil, nil, 24,
+ nil, 22, nil, nil, nil, 22, 22, nil, nil, nil,
+ nil, nil, nil, nil, nil, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, nil, 49, 49, 49,
nil, 22, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 49, 49, nil, nil, nil,
- nil, 23, 22, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 22, nil, nil, nil, nil, nil, 49,
+ nil, 22, 23, nil, nil, 24, nil, nil, nil, nil,
+ nil, nil, nil, 23, nil, 22, 24, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 22, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 22, 22, 22, nil, nil, nil, nil, 22,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 22, nil, nil, nil, 47, 47, nil, nil, nil,
- nil, nil, nil, nil, 22, nil, 22, 22, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 49, nil, 47,
- nil, nil, nil, nil, nil, nil, nil, 49, nil, 22,
- nil, 49, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 22, nil, nil, 47, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 47, nil, nil,
- nil, 47 ]
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 22, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 22 ]
racc_goto_pointer = [
- nil, 19, 1, 15, -27, 59, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -6, nil,
- nil, -75, 254, 161, 100, 42, -10, -16, 2, 53,
- 23, -1, -78, -36, -83, 0, -4, nil, -1, -73,
- -185, nil, nil, nil, -175, -25, nil, 289, -29, 249,
- -42, nil, -38, -50, -122, 11, -200, -103, -120, nil,
- -125, -86, -118, -133, 23, -39, 17, 43, 12, -3,
- -78, -76, -124, -35 ]
+ nil, 28, 6, 16, -17, 37, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, -5, nil,
+ nil, -76, 299, 186, 189, 112, 46, 57, 2, 0,
+ 9, 4, -74, -21, -105, 3, 2, nil, 17, -69,
+ -203, nil, nil, nil, -203, -14, nil, 33, -27, 301,
+ -17, 91, nil, -23, -22, -234, -200, -137, -152, nil,
+ -133, -96, -130, -164, 22, -52, 13, 41, 12, -5,
+ -117, -114, -164, -46 ]
racc_goto_default = [
- nil, nil, nil, 148, 8, 11, 14, 16, 19, 21,
- 23, 25, 28, 31, 2, 7, 10, 13, nil, 64,
- 66, 67, 83, 84, 85, 74, 75, 79, 80, 15,
- 17, nil, nil, nil, nil, 71, nil, 6, nil, nil,
- 150, 210, 152, 153, nil, nil, 126, 48, 76, nil,
- 117, 109, nil, nil, nil, nil, nil, nil, nil, 195,
- 53, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, 169, 26, 30, 32, 3, 7, 9,
+ 11, 12, 14, 18, 21, 25, 29, 31, nil, 50,
+ 53, 55, 77, 78, 79, 81, 82, 86, 87, 74,
+ 6, nil, nil, nil, nil, 61, nil, 24, nil, nil,
+ 163, 235, 164, 165, nil, nil, 119, 80, 83, nil,
+ 124, 73, 103, nil, nil, 196, nil, nil, nil, 242,
+ 68, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil ]
racc_token_table = {
@@ -613,11 +782,18 @@ racc_token_table = {
:OR => 48,
:AND => 49,
:UNDEF => 50,
- :PARROW => 51 }
+ :PARROW => 51,
+ :PLUS => 52,
+ :MINUS => 53,
+ :TIMES => 54,
+ :DIV => 55,
+ :LSHIFT => 56,
+ :RSHIFT => 57,
+ :UMINUS => 58 }
racc_use_result_var = true
-racc_nt_base = 52
+racc_nt_base = 59
Racc_arg = [
racc_action_table,
@@ -688,6 +864,13 @@ Racc_token_to_s_table = [
'AND',
'UNDEF',
'PARROW',
+'PLUS',
+'MINUS',
+'TIMES',
+'DIV',
+'LSHIFT',
+'RSHIFT',
+'UMINUS',
'$start',
'program',
'statements',
@@ -737,13 +920,13 @@ Racc_token_to_s_table = [
'resourcename',
'undef',
'array',
-'rvalue',
+'expression',
'param',
+'rvalue',
'addparam',
'anyparam',
'rvalues',
'comma',
-'iftest',
'else',
'caseopts',
'caseopt',
@@ -769,7 +952,7 @@ Racc_debug_parser = false
# reduce 0 omitted
-module_eval <<'.,.,', 'grammar.ra', 30
+module_eval <<'.,.,', 'grammar.ra', 42
def _reduce_1( val, _values, result )
if val[0]
# Make sure we always return an array.
@@ -793,7 +976,7 @@ module_eval <<'.,.,', 'grammar.ra', 30
# reduce 3 omitted
-module_eval <<'.,.,', 'grammar.ra', 46
+module_eval <<'.,.,', 'grammar.ra', 58
def _reduce_4( val, _values, result )
if val[0] and val[1]
if val[0].instance_of?(AST::ASTArray)
@@ -836,7 +1019,7 @@ module_eval <<'.,.,', 'grammar.ra', 46
# reduce 17 omitted
-module_eval <<'.,.,', 'grammar.ra', 69
+module_eval <<'.,.,', 'grammar.ra', 81
def _reduce_18( val, _values, result )
args = aryfy(val[2])
result = ast AST::Function,
@@ -847,7 +1030,7 @@ module_eval <<'.,.,', 'grammar.ra', 69
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 75
+module_eval <<'.,.,', 'grammar.ra', 87
def _reduce_19( val, _values, result )
result = ast AST::Function,
:name => val[0],
@@ -857,7 +1040,7 @@ module_eval <<'.,.,', 'grammar.ra', 75
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 82
+module_eval <<'.,.,', 'grammar.ra', 94
def _reduce_20( val, _values, result )
args = aryfy(val[1])
result = ast AST::Function,
@@ -874,7 +1057,7 @@ module_eval <<'.,.,', 'grammar.ra', 82
# reduce 23 omitted
-module_eval <<'.,.,', 'grammar.ra', 92
+module_eval <<'.,.,', 'grammar.ra', 104
def _reduce_24( val, _values, result )
result = aryfy(val[0], val[2])
result.line = @lexer.line
@@ -897,7 +1080,7 @@ module_eval <<'.,.,', 'grammar.ra', 92
# reduce 31 omitted
-module_eval <<'.,.,', 'grammar.ra', 105
+module_eval <<'.,.,', 'grammar.ra', 117
def _reduce_32( val, _values, result )
result = ast AST::Name, :value => val[0]
result
@@ -906,7 +1089,7 @@ module_eval <<'.,.,', 'grammar.ra', 105
# reduce 33 omitted
-module_eval <<'.,.,', 'grammar.ra', 116
+module_eval <<'.,.,', 'grammar.ra', 128
def _reduce_34( val, _values, result )
unless val[0].is_a?(AST::ASTArray)
val[0] = aryfy(val[0])
@@ -919,7 +1102,7 @@ module_eval <<'.,.,', 'grammar.ra', 116
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 137
+module_eval <<'.,.,', 'grammar.ra', 149
def _reduce_35( val, _values, result )
array = val[2]
if array.instance_of?(AST::ResourceInstance)
@@ -943,7 +1126,7 @@ module_eval <<'.,.,', 'grammar.ra', 137
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 140
+module_eval <<'.,.,', 'grammar.ra', 152
def _reduce_36( val, _values, result )
# This is a deprecated syntax.
error "All resource specifications require names"
@@ -951,7 +1134,7 @@ module_eval <<'.,.,', 'grammar.ra', 140
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 143
+module_eval <<'.,.,', 'grammar.ra', 155
def _reduce_37( val, _values, result )
# a defaults setting for a type
result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2])
@@ -959,14 +1142,14 @@ module_eval <<'.,.,', 'grammar.ra', 143
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 148
+module_eval <<'.,.,', 'grammar.ra', 160
def _reduce_38( val, _values, result )
result = ast AST::ResourceOverride, :object => val[0], :params => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 175
+module_eval <<'.,.,', 'grammar.ra', 187
def _reduce_39( val, _values, result )
type = val[0]
@@ -994,21 +1177,21 @@ module_eval <<'.,.,', 'grammar.ra', 175
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 176
+module_eval <<'.,.,', 'grammar.ra', 188
def _reduce_40( val, _values, result )
result = :virtual
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 177
+module_eval <<'.,.,', 'grammar.ra', 189
def _reduce_41( val, _values, result )
result = :exported
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 200
+module_eval <<'.,.,', 'grammar.ra', 212
def _reduce_42( val, _values, result )
if val[0] =~ /^[a-z]/
Puppet.warning addcontext("Collection names must now be capitalized")
@@ -1031,7 +1214,7 @@ module_eval <<'.,.,', 'grammar.ra', 200
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 210
+module_eval <<'.,.,', 'grammar.ra', 222
def _reduce_43( val, _values, result )
if val[1]
result = val[1]
@@ -1043,7 +1226,7 @@ module_eval <<'.,.,', 'grammar.ra', 210
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 218
+module_eval <<'.,.,', 'grammar.ra', 230
def _reduce_44( val, _values, result )
if val[1]
result = val[1]
@@ -1059,7 +1242,7 @@ module_eval <<'.,.,', 'grammar.ra', 218
# reduce 46 omitted
-module_eval <<'.,.,', 'grammar.ra', 226
+module_eval <<'.,.,', 'grammar.ra', 238
def _reduce_47( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
result
@@ -1068,7 +1251,7 @@ module_eval <<'.,.,', 'grammar.ra', 226
# reduce 48 omitted
-module_eval <<'.,.,', 'grammar.ra', 232
+module_eval <<'.,.,', 'grammar.ra', 244
def _reduce_49( val, _values, result )
result = val[1]
result.parens = true
@@ -1080,7 +1263,7 @@ module_eval <<'.,.,', 'grammar.ra', 232
# reduce 51 omitted
-module_eval <<'.,.,', 'grammar.ra', 240
+module_eval <<'.,.,', 'grammar.ra', 252
def _reduce_52( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
#result = ast AST::CollExpr
@@ -1089,7 +1272,7 @@ module_eval <<'.,.,', 'grammar.ra', 240
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 245
+module_eval <<'.,.,', 'grammar.ra', 257
def _reduce_53( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
#result = ast AST::CollExpr
@@ -1102,7 +1285,7 @@ module_eval <<'.,.,', 'grammar.ra', 245
# reduce 55 omitted
-module_eval <<'.,.,', 'grammar.ra', 252
+module_eval <<'.,.,', 'grammar.ra', 264
def _reduce_56( val, _values, result )
result = ast AST::ResourceInstance, :children => [val[0],val[2]]
result
@@ -1111,7 +1294,7 @@ module_eval <<'.,.,', 'grammar.ra', 252
# reduce 57 omitted
-module_eval <<'.,.,', 'grammar.ra', 262
+module_eval <<'.,.,', 'grammar.ra', 274
def _reduce_58( val, _values, result )
if val[0].instance_of?(AST::ResourceInstance)
result = ast AST::ASTArray, :children => [val[0],val[2]]
@@ -1127,21 +1310,21 @@ module_eval <<'.,.,', 'grammar.ra', 262
# reduce 60 omitted
-module_eval <<'.,.,', 'grammar.ra', 269
+module_eval <<'.,.,', 'grammar.ra', 281
def _reduce_61( val, _values, result )
result = ast AST::Undef, :value => :undef
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 273
+module_eval <<'.,.,', 'grammar.ra', 285
def _reduce_62( val, _values, result )
result = ast AST::Name, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 277
+module_eval <<'.,.,', 'grammar.ra', 289
def _reduce_63( val, _values, result )
result = ast AST::Type, :value => val[0]
result
@@ -1160,7 +1343,7 @@ module_eval <<'.,.,', 'grammar.ra', 277
# reduce 69 omitted
-module_eval <<'.,.,', 'grammar.ra', 293
+module_eval <<'.,.,', 'grammar.ra', 305
def _reduce_70( val, _values, result )
if val[0] =~ /::/
raise Puppet::ParseError, "Cannot assign to variables in other namespaces"
@@ -1172,7 +1355,7 @@ module_eval <<'.,.,', 'grammar.ra', 293
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 298
+module_eval <<'.,.,', 'grammar.ra', 310
def _reduce_71( val, _values, result )
variable = ast AST::Name, :value => val[0]
result = ast AST::VarDef, :name => variable, :value => val[2], :append => true
@@ -1180,21 +1363,21 @@ module_eval <<'.,.,', 'grammar.ra', 298
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 303
+module_eval <<'.,.,', 'grammar.ra', 315
def _reduce_72( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 303
+module_eval <<'.,.,', 'grammar.ra', 315
def _reduce_73( val, _values, result )
result = val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 312
+module_eval <<'.,.,', 'grammar.ra', 324
def _reduce_74( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
@@ -1206,14 +1389,14 @@ module_eval <<'.,.,', 'grammar.ra', 312
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 316
+module_eval <<'.,.,', 'grammar.ra', 328
def _reduce_75( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 321
+module_eval <<'.,.,', 'grammar.ra', 333
def _reduce_76( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2],
:add => true
@@ -1225,21 +1408,21 @@ module_eval <<'.,.,', 'grammar.ra', 321
# reduce 78 omitted
-module_eval <<'.,.,', 'grammar.ra', 329
+module_eval <<'.,.,', 'grammar.ra', 341
def _reduce_79( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 329
+module_eval <<'.,.,', 'grammar.ra', 341
def _reduce_80( val, _values, result )
result = val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 338
+module_eval <<'.,.,', 'grammar.ra', 350
def _reduce_81( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
@@ -1253,7 +1436,7 @@ module_eval <<'.,.,', 'grammar.ra', 338
# reduce 82 omitted
-module_eval <<'.,.,', 'grammar.ra', 347
+module_eval <<'.,.,', 'grammar.ra', 359
def _reduce_83( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
result = val[0].push(val[2])
@@ -1296,7 +1479,7 @@ module_eval <<'.,.,', 'grammar.ra', 347
# reduce 99 omitted
-module_eval <<'.,.,', 'grammar.ra', 374
+module_eval <<'.,.,', 'grammar.ra', 386
def _reduce_100( val, _values, result )
args = aryfy(val[2])
result = ast AST::Function,
@@ -1307,7 +1490,7 @@ module_eval <<'.,.,', 'grammar.ra', 374
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 379
+module_eval <<'.,.,', 'grammar.ra', 391
def _reduce_101( val, _values, result )
result = ast AST::Function,
:name => val[0],
@@ -1317,28 +1500,28 @@ module_eval <<'.,.,', 'grammar.ra', 379
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 383
+module_eval <<'.,.,', 'grammar.ra', 395
def _reduce_102( val, _values, result )
result = ast AST::String, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 385
+module_eval <<'.,.,', 'grammar.ra', 397
def _reduce_103( val, _values, result )
result = ast AST::FlatString, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 389
+module_eval <<'.,.,', 'grammar.ra', 401
def _reduce_104( val, _values, result )
result = ast AST::Boolean, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 394
+module_eval <<'.,.,', 'grammar.ra', 406
def _reduce_105( val, _values, result )
Puppet.warning addcontext("Deprecation notice: Resource references should now be capitalized")
result = ast AST::ResourceReference, :type => val[0], :title => val[2]
@@ -1346,14 +1529,14 @@ module_eval <<'.,.,', 'grammar.ra', 394
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 396
+module_eval <<'.,.,', 'grammar.ra', 408
def _reduce_106( val, _values, result )
result = ast AST::ResourceReference, :type => val[0], :title => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 409
+module_eval <<'.,.,', 'grammar.ra', 421
def _reduce_107( val, _values, result )
args = {
:test => val[1],
@@ -1369,19 +1552,161 @@ module_eval <<'.,.,', 'grammar.ra', 409
end
.,.,
- # reduce 108 omitted
+module_eval <<'.,.,', 'grammar.ra', 433
+ def _reduce_108( val, _values, result )
+ args = {
+ :test => val[1],
+ :statements => ast(AST::Nop)
+ }
-module_eval <<'.,.,', 'grammar.ra', 414
- def _reduce_109( val, _values, result )
- result = ast AST::Else, :statements => val[2]
+ if val[4]
+ args[:else] = val[4]
+ end
+
+ result = ast AST::IfStatement, args
result
end
.,.,
- # reduce 110 omitted
+ # reduce 109 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 438
+ def _reduce_110( val, _values, result )
+ result = ast AST::Else, :statements => val[2]
+ result
+ end
+.,.,
-module_eval <<'.,.,', 'grammar.ra', 426
+module_eval <<'.,.,', 'grammar.ra', 441
def _reduce_111( val, _values, result )
+ result = ast AST::Else, :statements => ast(AST::Nop)
+ result
+ end
+.,.,
+
+ # reduce 112 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 458
+ def _reduce_113( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 461
+ def _reduce_114( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 464
+ def _reduce_115( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 467
+ def _reduce_116( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 470
+ def _reduce_117( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 473
+ def _reduce_118( val, _values, result )
+ result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 476
+ def _reduce_119( val, _values, result )
+ result = ast AST::Minus, :value => val[1]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 479
+ def _reduce_120( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 482
+ def _reduce_121( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 485
+ def _reduce_122( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 488
+ def _reduce_123( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 491
+ def _reduce_124( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 494
+ def _reduce_125( val, _values, result )
+ result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 497
+ def _reduce_126( val, _values, result )
+ result = ast AST::Not, :value => val[1]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 500
+ def _reduce_127( val, _values, result )
+ result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 503
+ def _reduce_128( val, _values, result )
+ result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 506
+ def _reduce_129( val, _values, result )
+ result = val[1]
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 514
+ def _reduce_130( val, _values, result )
options = val[3]
unless options.instance_of?(AST::ASTArray)
options = ast AST::ASTArray, :children => [val[3]]
@@ -1391,10 +1716,10 @@ module_eval <<'.,.,', 'grammar.ra', 426
end
.,.,
- # reduce 112 omitted
+ # reduce 131 omitted
-module_eval <<'.,.,', 'grammar.ra', 436
- def _reduce_113( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 524
+ def _reduce_132( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push val[1]
result = val[0]
@@ -1405,15 +1730,15 @@ module_eval <<'.,.,', 'grammar.ra', 436
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 440
- def _reduce_114( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 528
+ def _reduce_133( val, _values, result )
result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 445
- def _reduce_115( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 533
+ def _reduce_134( val, _values, result )
result = ast(AST::CaseOpt,
:value => val[0],
:statements => ast(AST::ASTArray)
@@ -1422,10 +1747,10 @@ module_eval <<'.,.,', 'grammar.ra', 445
end
.,.,
- # reduce 116 omitted
+ # reduce 135 omitted
-module_eval <<'.,.,', 'grammar.ra', 455
- def _reduce_117( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 543
+ def _reduce_136( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1436,26 +1761,26 @@ module_eval <<'.,.,', 'grammar.ra', 455
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 459
- def _reduce_118( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 547
+ def _reduce_137( val, _values, result )
result = ast AST::Selector, :param => val[0], :values => val[2]
result
end
.,.,
- # reduce 119 omitted
+ # reduce 138 omitted
-module_eval <<'.,.,', 'grammar.ra', 461
- def _reduce_120( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 549
+ def _reduce_139( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 121 omitted
+ # reduce 140 omitted
-module_eval <<'.,.,', 'grammar.ra', 472
- def _reduce_122( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 560
+ def _reduce_141( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1466,50 +1791,50 @@ module_eval <<'.,.,', 'grammar.ra', 472
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 476
- def _reduce_123( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 564
+ def _reduce_142( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2]
result
end
.,.,
- # reduce 124 omitted
+ # reduce 143 omitted
- # reduce 125 omitted
+ # reduce 144 omitted
- # reduce 126 omitted
+ # reduce 145 omitted
- # reduce 127 omitted
+ # reduce 146 omitted
- # reduce 128 omitted
+ # reduce 147 omitted
- # reduce 129 omitted
+ # reduce 148 omitted
- # reduce 130 omitted
+ # reduce 149 omitted
-module_eval <<'.,.,', 'grammar.ra', 487
- def _reduce_131( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 575
+ def _reduce_150( val, _values, result )
result = ast AST::Default, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 489
- def _reduce_132( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 577
+ def _reduce_151( val, _values, result )
result = [val[0].value]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 493
- def _reduce_133( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 581
+ def _reduce_152( val, _values, result )
results = val[0] << val[2].value
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 501
- def _reduce_134( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 589
+ def _reduce_153( val, _values, result )
val[1].each do |file|
import(file)
end
@@ -1519,8 +1844,8 @@ module_eval <<'.,.,', 'grammar.ra', 501
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 511
- def _reduce_135( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 599
+ def _reduce_154( val, _values, result )
newdefine classname(val[1]), :arguments => val[2], :code => val[4]
@lexer.indefine = false
result = nil
@@ -1530,8 +1855,8 @@ module_eval <<'.,.,', 'grammar.ra', 511
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 515
- def _reduce_136( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 603
+ def _reduce_155( val, _values, result )
newdefine classname(val[1]), :arguments => val[2]
@lexer.indefine = false
result = nil
@@ -1539,8 +1864,8 @@ module_eval <<'.,.,', 'grammar.ra', 515
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 523
- def _reduce_137( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 611
+ def _reduce_156( val, _values, result )
# Our class gets defined in the parent namespace, not our own.
@lexer.namepop
newclass classname(val[1]), :code => val[4], :parent => val[2]
@@ -1549,8 +1874,8 @@ module_eval <<'.,.,', 'grammar.ra', 523
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 528
- def _reduce_138( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 616
+ def _reduce_157( val, _values, result )
# Our class gets defined in the parent namespace, not our own.
@lexer.namepop
newclass classname(val[1]), :parent => val[2]
@@ -1559,32 +1884,32 @@ module_eval <<'.,.,', 'grammar.ra', 528
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 533
- def _reduce_139( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 621
+ def _reduce_158( val, _values, result )
newnode val[1], :parent => val[2], :code => val[4]
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 536
- def _reduce_140( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 624
+ def _reduce_159( val, _values, result )
newnode val[1], :parent => val[2]
result = nil
result
end
.,.,
- # reduce 141 omitted
+ # reduce 160 omitted
- # reduce 142 omitted
+ # reduce 161 omitted
- # reduce 143 omitted
+ # reduce 162 omitted
- # reduce 144 omitted
+ # reduce 163 omitted
-module_eval <<'.,.,', 'grammar.ra', 550
- def _reduce_145( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 638
+ def _reduce_164( val, _values, result )
result = val[0]
result = [result] unless result.is_a?(Array)
result << val[2]
@@ -1592,49 +1917,49 @@ module_eval <<'.,.,', 'grammar.ra', 550
end
.,.,
- # reduce 146 omitted
+ # reduce 165 omitted
- # reduce 147 omitted
+ # reduce 166 omitted
- # reduce 148 omitted
+ # reduce 167 omitted
- # reduce 149 omitted
+ # reduce 168 omitted
-module_eval <<'.,.,', 'grammar.ra', 559
- def _reduce_150( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 647
+ def _reduce_169( val, _values, result )
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 563
- def _reduce_151( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 651
+ def _reduce_170( val, _values, result )
result = ast AST::ASTArray, :children => []
result
end
.,.,
- # reduce 152 omitted
+ # reduce 171 omitted
-module_eval <<'.,.,', 'grammar.ra', 568
- def _reduce_153( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 656
+ def _reduce_172( val, _values, result )
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 572
- def _reduce_154( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 660
+ def _reduce_173( val, _values, result )
result = val[1]
result = [result] unless result[0].is_a?(Array)
result
end
.,.,
- # reduce 155 omitted
+ # reduce 174 omitted
-module_eval <<'.,.,', 'grammar.ra', 579
- def _reduce_156( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 667
+ def _reduce_175( val, _values, result )
result = val[0]
result = [result] unless result[0].is_a?(Array)
result << val[2]
@@ -1642,67 +1967,67 @@ module_eval <<'.,.,', 'grammar.ra', 579
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 584
- def _reduce_157( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 672
+ def _reduce_176( val, _values, result )
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0], val[2]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 588
- def _reduce_158( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 676
+ def _reduce_177( val, _values, result )
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 590
- def _reduce_159( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 678
+ def _reduce_178( val, _values, result )
result = [val[0], val[2]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 592
- def _reduce_160( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 680
+ def _reduce_179( val, _values, result )
result = [val[0]]
result
end
.,.,
- # reduce 161 omitted
+ # reduce 180 omitted
-module_eval <<'.,.,', 'grammar.ra', 597
- def _reduce_162( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 685
+ def _reduce_181( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 163 omitted
+ # reduce 182 omitted
-module_eval <<'.,.,', 'grammar.ra', 602
- def _reduce_164( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 690
+ def _reduce_183( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 165 omitted
+ # reduce 184 omitted
- # reduce 166 omitted
+ # reduce 185 omitted
-module_eval <<'.,.,', 'grammar.ra', 608
- def _reduce_167( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 696
+ def _reduce_186( val, _values, result )
result = ast AST::Variable, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 616
- def _reduce_168( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 704
+ def _reduce_187( val, _values, result )
if val[1].instance_of?(AST::ASTArray)
result = val[1]
else
@@ -1712,21 +2037,21 @@ module_eval <<'.,.,', 'grammar.ra', 616
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 618
- def _reduce_169( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 706
+ def _reduce_188( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
- # reduce 170 omitted
+ # reduce 189 omitted
- # reduce 171 omitted
+ # reduce 190 omitted
- # reduce 172 omitted
+ # reduce 191 omitted
-module_eval <<'.,.,', 'grammar.ra', 623
- def _reduce_173( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 711
+ def _reduce_192( val, _values, result )
result = nil
result
end
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 1ff998d96..4acdf41c9 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -43,6 +43,29 @@ class Puppet::Parser::Scope
end
end
+ # Is the value a number?, return the correct object or nil if not a number
+ def self.number?(value)
+ unless value.is_a?(Fixnum) or value.is_a?(Bignum) or value.is_a?(Float) or value.is_a?(String)
+ return nil
+ end
+
+ if value.is_a?(String)
+ if value =~ /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/
+ return value.to_f
+ elsif value =~ /^0x\d+/i
+ return value.to_i(16)
+ elsif value =~ /^0\d+/i
+ return value.to_i(8)
+ elsif value =~ /^-?\d+/
+ return value.to_i
+ else
+ return nil
+ end
+ end
+ # it is one of Fixnum,Bignum or Float
+ return value
+ end
+
# Add to our list of namespaces.
def add_namespace(ns)
return false if @namespaces.include?(ns)
diff --git a/lib/puppet/property/list.rb b/lib/puppet/property/list.rb
new file mode 100644
index 000000000..4e7f6ec90
--- /dev/null
+++ b/lib/puppet/property/list.rb
@@ -0,0 +1,78 @@
+require 'puppet/property'
+
+module Puppet
+ class Property
+ class List < Property
+
+ def should_to_s(should_value)
+ #just return the should value
+ should_value
+ end
+
+ def is_to_s(currentvalue)
+ currentvalue.join(delimiter)
+ end
+
+ def membership
+ :membership
+ end
+
+ def add_should_with_current(should, current)
+ if current.is_a?(Array)
+ should += current
+ end
+ should.uniq
+ end
+
+ def inclusive?
+ @resource[membership] == :inclusive
+ end
+
+ def should
+ unless defined? @should and @should
+ return nil
+ end
+
+ members = @should
+ #inclusive means we are managing everything so if it isn't in should, its gone
+ if ! inclusive?
+ members = add_should_with_current(members, retrieve)
+ end
+
+ members.sort.join(delimiter)
+ end
+
+ def delimiter
+ ","
+ end
+
+ def retrieve
+ #ok, some 'convention' if the list property is named groups, provider should implement a groups method
+ if tmp = provider.send(name) and tmp != :absent
+ return tmp.split(delimiter)
+ else
+ return :absent
+ end
+ end
+
+ def prepare_is_for_comparison(is)
+ if is.is_a? Array
+ is = is.sort.join(delimiter)
+ end
+ is
+ end
+
+ def insync?(is)
+ unless defined? @should and @should
+ return true
+ end
+
+ unless is
+ return true
+ end
+
+ return (prepare_is_for_comparison(is) == self.should)
+ end
+ end
+ end
+end
diff --git a/lib/puppet/provider/nameservice.rb b/lib/puppet/provider/nameservice.rb
index 9764b5cf8..c1e21af08 100644
--- a/lib/puppet/provider/nameservice.rb
+++ b/lib/puppet/provider/nameservice.rb
@@ -179,11 +179,33 @@ class Puppet::Provider::NameService < Puppet::Provider
end
def create
- self.ensure = :present
+ if exists?
+ info "already exists"
+ # The object already exists
+ return nil
+ end
+
+ begin
+ execute(self.addcmd)
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not create %s %s: %s" %
+ [@resource.class.name, @resource.name, detail]
+ end
end
def delete
- self.ensure = :absent
+ unless exists?
+ info "already absent"
+ # the object already doesn't exist
+ return nil
+ end
+
+ begin
+ execute(self.deletecmd)
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not delete %s %s: %s" %
+ [@resource.class.name, @resource.name, detail]
+ end
end
def ensure
@@ -194,43 +216,6 @@ class Puppet::Provider::NameService < Puppet::Provider
end
end
- # This is only used when creating or destroying the object.
- def ensure=(value)
- cmd = nil
- event = nil
- case value
- when :absent
- # we need to remove the object...
- unless exists?
- info "already absent"
- # the object already doesn't exist
- return nil
- end
-
- # again, needs to be set by the ind. property or its
- # parent
- cmd = self.deletecmd
- type = "delete"
- when :present
- if exists?
- info "already exists"
- # The object already exists
- return nil
- end
-
- # blah blah, define elsewhere, blah blah
- cmd = self.addcmd
- type = "create"
- end
-
- begin
- execute(cmd)
- rescue Puppet::ExecutionFailure => detail
- raise Puppet::Error, "Could not %s %s %s: %s" %
- [type, @resource.class.name, @resource.name, detail]
- end
- end
-
# Does our object exist?
def exists?
if getinfo(true)
diff --git a/lib/puppet/provider/nameservice/directoryservice.rb b/lib/puppet/provider/nameservice/directoryservice.rb
index e2e68b2ca..fcc44f9e3 100644
--- a/lib/puppet/provider/nameservice/directoryservice.rb
+++ b/lib/puppet/provider/nameservice/directoryservice.rb
@@ -206,9 +206,18 @@ class DirectoryService < Puppet::Provider::NameService
if ensure_value == :present
@resource.class.validproperties.each do |name|
next if name == :ensure
- next unless val = @resource.should(name) || autogen(name)
- # JJM: This calls the method.
- self.send(name.to_s + "=", val)
+
+ # LAK: We use property.sync here rather than directly calling
+ # the settor method because the properties might do some kind
+ # of conversion. In particular, the user gid property might
+ # have a string and need to convert it to a number
+ if @resource.should(name)
+ @resource.property(name).sync
+ elsif value = autogen(name)
+ self.send(name.to_s + "=", value)
+ else
+ next
+ end
end
end
end
diff --git a/lib/puppet/provider/nameservice/netinfo.rb b/lib/puppet/provider/nameservice/netinfo.rb
index 29600052b..ac7bc94b1 100644
--- a/lib/puppet/provider/nameservice/netinfo.rb
+++ b/lib/puppet/provider/nameservice/netinfo.rb
@@ -138,8 +138,18 @@ class NetInfo < Puppet::Provider::NameService
if arg == :present
@resource.class.validproperties.each do |name|
next if name == :ensure
- next unless val = @resource.should(name) || autogen(name)
- self.send(name.to_s + "=", val)
+
+ # LAK: We use property.sync here rather than directly calling
+ # the settor method because the properties might do some kind
+ # of conversion. In particular, the user gid property might
+ # have a string and need to convert it to a number
+ if @resource.should(name)
+ @resource.property(name).sync
+ elsif value = autogen(name)
+ self.send(name.to_s + "=", value)
+ else
+ next
+ end
end
end
end
diff --git a/lib/puppet/provider/nameservice/objectadd.rb b/lib/puppet/provider/nameservice/objectadd.rb
index b7efe8388..256368ee1 100644
--- a/lib/puppet/provider/nameservice/objectadd.rb
+++ b/lib/puppet/provider/nameservice/objectadd.rb
@@ -2,15 +2,6 @@ require 'puppet/provider/nameservice'
class Puppet::Provider::NameService
class ObjectAdd < Puppet::Provider::NameService
- # Does the object already exist?
- def self.exists?(obj)
- if obj.getinfo(true)
- return true
- else
- return false
- end
- end
-
def deletecmd
[command(:delete), @resource[:name]]
end
@@ -23,7 +14,7 @@ class ObjectAdd < Puppet::Provider::NameService
def modifycmd(param, value)
cmd = [command(:modify), flag(param), value]
- if @resource.allowdupe? && ((param == :uid and self.class.name == :useradd) || (param == :gid and self.class.name == :groupadd))
+ if @resource.allowdupe? && ((param == :uid) || (param == :gid and self.class.name == :groupadd))
cmd << "-o"
end
cmd << @resource[:name]
diff --git a/lib/puppet/provider/package/apt.rb b/lib/puppet/provider/package/apt.rb
index d0e520f0a..80465129d 100755
--- a/lib/puppet/provider/package/apt.rb
+++ b/lib/puppet/provider/package/apt.rb
@@ -45,9 +45,19 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
if @resource[:responsefile]
self.run_preseed
end
- should = @resource.should(:ensure)
+ should = @resource[:ensure]
checkforcdrom()
+ cmd = %w{-q -y}
+
+ keep = ""
+ if config = @resource[:configfiles]
+ if config == :keep
+ cmd << "-o" << 'DPkg::Options::=--force-confold'
+ else
+ cmd << "-o" << 'DPkg::Options::=--force-confnew'
+ end
+ end
str = @resource[:name]
case should
@@ -57,19 +67,6 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
# Add the package version
str += "=%s" % should
end
- cmd = %w{-q -y}
-
- keep = ""
- if config = @resource[:configfiles]
- case config
- when :keep
- cmd << "-o" << 'DPkg::Options::=--force-confold'
- when :replace
- cmd << "-o" << 'DPkg::Options::=--force-confnew'
- else
- raise Puppet::Error, "Invalid 'configfiles' value %s" % config
- end
- end
cmd << :install << str
@@ -92,7 +89,7 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
# preseeds answers to dpkg-set-selection from the "responsefile"
#
def run_preseed
- if response = @resource[:responsefile] and FileTest.exists?(response)
+ if response = @resource[:responsefile] and FileTest.exist?(response)
self.info("Preseeding %s to debconf-set-selections" % response)
preseed response
@@ -101,16 +98,12 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
end
end
- def update
- self.install
- end
-
def uninstall
aptget "-y", "-q", :remove, @resource[:name]
end
def purge
- aptget '-y', '-q', 'remove', '--purge', @resource[:name]
+ aptget '-y', '-q', :remove, '--purge', @resource[:name]
# workaround a "bug" in apt, that already removed packages are not purged
super
end
diff --git a/lib/puppet/provider/package/dpkg.rb b/lib/puppet/provider/package/dpkg.rb
index ae79f714c..67d31a592 100755
--- a/lib/puppet/provider/package/dpkg.rb
+++ b/lib/puppet/provider/package/dpkg.rb
@@ -23,30 +23,39 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
# now turn each returned line into a package object
process.each { |line|
- if match = regex.match(line)
- hash = {}
+ if hash = parse_line(line)
+ packages << new(hash)
+ end
+ }
+ end
- fields.zip(match.captures) { |field,value|
- hash[field] = value
- }
+ return packages
+ end
- hash[:provider] = self.name
+ REGEX = %r{^(\S+) +(\S+) +(\S+) (\S+) (\S*)$}
+ FIELDS = [:desired, :error, :status, :name, :ensure]
- if hash[:status] == 'not-installed'
- hash[:ensure] = :purged
- elsif hash[:status] != "installed"
- hash[:ensure] = :absent
- end
+ def self.parse_line(line)
+ if match = REGEX.match(line)
+ hash = {}
- packages << new(hash)
- else
- Puppet.warning "Failed to match dpkg-query line %s" %
- line.inspect
- end
+ FIELDS.zip(match.captures) { |field,value|
+ hash[field] = value
}
+
+ hash[:provider] = self.name
+
+ if hash[:status] == 'not-installed'
+ hash[:ensure] = :purged
+ elsif hash[:status] != "installed"
+ hash[:ensure] = :absent
+ end
+ else
+ Puppet.warning "Failed to match dpkg-query line %s" % line.inspect
+ return nil
end
- return packages
+ return hash
end
def install
@@ -56,15 +65,10 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
args = []
- if config = @resource[:configfiles]
- case config
- when :keep
- args << '--force-confold'
- when :replace
- args << '--force-confnew'
- else
- raise Puppet::Error, "Invalid 'configfiles' value %s" % config
- end
+ if @resource[:configfiles] == :keep
+ args << '--force-confold'
+ else
+ args << '--force-confnew'
end
args << '-i' << file
@@ -80,7 +84,7 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
output = dpkg_deb "--show", @resource[:source]
matches = /^(\S+)\t(\S+)$/.match(output).captures
unless matches[0].match(@resource[:name])
- Puppet.warning "source doesn't contain named package, but %s" % matches[0]
+ warning "source doesn't contain named package, but %s" % matches[0]
end
matches[1]
end
@@ -103,22 +107,8 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
:name => @resource[:name], :error => 'ok'}
end
- # Our regex for matching dpkg-query output. We could probably just
- # use split here, but I'm not positive that dpkg-query will never
- # return whitespace.
- regex = %r{^(\S+) (\S+) (\S+) (\S+) (\S*)$}
- line = output.split("\n").shift.chomp
-
- if match = regex.match(line)
- fields.zip(match.captures) { |field,value|
- hash[field] = value
- }
- else
- notice "Failed to handle dpkg-query line %s" % line.inspect
- return {:ensure => :absent, :status => 'missing',
- :name => @resource[:name], :error => 'ok'}
- end
+ hash = self.class.parse_line(output) || {:ensure => :absent, :status => 'missing', :name => @resource[:name], :error => 'ok'}
if hash[:error] != "ok"
raise Puppet::Error.new(
@@ -127,13 +117,6 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
)
end
- # DPKG can discuss packages that are no longer installed, so allow that.
- if hash[:status] == "not-installed"
- hash[:ensure] = :purged
- elsif hash[:status] != "installed"
- hash[:ensure] = :absent
- end
-
return hash
end
@@ -145,4 +128,3 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
dpkg "--purge", @resource[:name]
end
end
-
diff --git a/lib/puppet/provider/package/portage.rb b/lib/puppet/provider/package/portage.rb
index b382d80da..ae7194f89 100644
--- a/lib/puppet/provider/package/portage.rb
+++ b/lib/puppet/provider/package/portage.rb
@@ -72,7 +72,7 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
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]
- search_field = @resource[:category] ? "--category-name" : "--name"
+ search_field = package_name.count('/') > 0 ? "--category-name" : "--name"
search_value = package_name
search_format = "<category> <name> [<installedversionsshort>] [<best>] <homepage> <description>"
diff --git a/lib/puppet/provider/package/rpm.rb b/lib/puppet/provider/package/rpm.rb
index a303da4e2..b5a5c5dbc 100755
--- a/lib/puppet/provider/package/rpm.rb
+++ b/lib/puppet/provider/package/rpm.rb
@@ -23,9 +23,16 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
def self.instances
packages = []
+ # rpm < 4.1 don't support --nosignature
+ output = rpm "--version"
+ sig = "--nosignature"
+ if output =~ /RPM version (([123].*)|(4\.0.*))/
+ sig = ""
+ end
+
# list out all of the packages
begin
- execpipe("#{command(:rpm)} -qa --nosignature --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
+ execpipe("#{command(:rpm)} -qa #{sig} --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
# now turn each returned line into a package object
process.each { |line|
hash = nevra_to_hash(line)
diff --git a/lib/puppet/provider/package/rug.rb b/lib/puppet/provider/package/rug.rb
index c5451ad71..1e1d6763f 100644
--- a/lib/puppet/provider/package/rug.rb
+++ b/lib/puppet/provider/package/rug.rb
@@ -5,8 +5,8 @@ Puppet.type(:package).provide :rug, :parent => :rpm do
commands :rug => "/usr/bin/rug"
commands :rpm => "rpm"
- defaultfor :operatingsystem => :suse
- confine :operatingsystem => :suse
+ defaultfor :operatingsystem => [:suse, :sles]
+ confine :operatingsystem => [:suse, :sles]
# Install a package using 'rug'.
def install
diff --git a/lib/puppet/provider/package/yumhelper.py b/lib/puppet/provider/package/yumhelper.py
index 962b96ce4..8eab0d081 100644
--- a/lib/puppet/provider/package/yumhelper.py
+++ b/lib/puppet/provider/package/yumhelper.py
@@ -4,8 +4,23 @@
# (C) 2007 Red Hat Inc.
# David Lutterkort <dlutter @redhat.com>
-import yum
import sys
+import string
+import re
+
+# this maintains compatibility with really old platforms with python 1.x
+from os import popen, WEXITSTATUS
+
+# Try to use the yum libraries by default, but shell out to the yum executable
+# if they are not present (i.e. yum <= 2.0). This is only required for RHEL3
+# and earlier that do not support later versions of Yum. Once RHEL3 is EOL,
+# shell_out() and related code can be removed.
+try:
+ import yum
+except ImportError:
+ useyumlib = 0
+else:
+ useyumlib = 1
OVERRIDE_OPTS = {
'debuglevel': 0,
@@ -26,14 +41,80 @@ def pkg_lists(my):
my.doRpmDBSetup()
return my.doPackageLists('updates')
-try:
+def shell_out():
+ try:
+ p = popen("/usr/bin/env yum check-update 2>&1")
+ output = p.readlines()
+ rc = p.close()
+
+ if rc is not None:
+ # None represents exit code of 0, otherwise the exit code is in the
+ # format returned by wait(). Exit code of 100 from yum represents
+ # updates available.
+ if WEXITSTATUS(rc) != 100:
+ return WEXITSTATUS(rc)
+ else:
+ # Exit code is None (0), no updates waiting so don't both parsing output
+ return 0
+
+ # Yum prints a line of hyphens (old versions) or a blank line between
+ # headers and package data, so skip everything before them
+ skipheaders = 0
+ for line in output:
+ if not skipheaders:
+ if re.compile("^((-){80}|)$").search(line):
+ skipheaders = 1
+ continue
+
+ # Skip any blank lines
+ if re.compile("^[ \t]*$").search(line):
+ continue
+
+ # Format is:
+ # Yum 1.x: name arch (epoch:)?version
+ # Yum 2.0: name arch (epoch:)?version repo
+ # epoch is optional if 0
+
+ p = string.split(line)
+ pname = p[0]
+ parch = p[1]
+ pevr = p[2]
+
+ # Separate out epoch:version-release
+ evr_re = re.compile("^(\d:)?(\S+)-(\S+)$")
+ evr = evr_re.match(pevr)
+
+ pepoch = ""
+ if evr.group(1) is None:
+ pepoch = "0"
+ else:
+ pepoch = evr.group(1).replace(":", "")
+ pversion = evr.group(2)
+ prelease = evr.group(3)
+
+ print "_pkg", pname, pepoch, pversion, prelease, parch
+
+ return 0
+ except:
+ print sys.exc_info()[0]
+ return 1
+
+if useyumlib:
try:
- my = yum.YumBase()
- ypl = pkg_lists(my)
- for pkg in ypl.updates:
- print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
- finally:
- my.closeRpmDB()
-except IOError, e:
- print "_err IOError %d %s" % (e.errno, e)
- sys.exit(1)
+ try:
+ my = yum.YumBase()
+ ypl = pkg_lists(my)
+ for pkg in ypl.updates:
+ print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
+ finally:
+ my.closeRpmDB()
+ except IOError, e:
+ print "_err IOError %d %s" % (e.errno, e)
+ sys.exit(1)
+ except AttributeError, e:
+ # catch yumlib errors in buggy 2.x versions of yum
+ print "_err AttributeError %s" % e
+ sys.exit(1)
+else:
+ rc = shell_out()
+ sys.exit(rc)
diff --git a/lib/puppet/provider/selboolean/getsetsebool.rb b/lib/puppet/provider/selboolean/getsetsebool.rb
new file mode 100644
index 000000000..4614c6c38
--- /dev/null
+++ b/lib/puppet/provider/selboolean/getsetsebool.rb
@@ -0,0 +1,47 @@
+Puppet::Type.type(:selboolean).provide(:getsetsebool) do
+ desc "Manage SELinux booleans using the getsebool and setsebool binaries."
+
+ commands :getsebool => "/usr/sbin/getsebool"
+ commands :setsebool => "/usr/sbin/setsebool"
+
+ def value
+ self.debug "Retrieving value of selboolean #{@resource[:name]}"
+
+ status = getsebool(@resource[:name])
+
+ if status =~ / off$/ then
+ return :off
+ elsif status =~ / on$/ then
+ return :on
+ else
+ status.chomp!
+ raise Puppet::Error, "Invalid response '%s' returned from getsebool" % [status]
+ end
+ end
+
+ def value=(new)
+ persist = ""
+ if @resource[:persistent] == :true
+ self.debug "Enabling persistence"
+ persist = "-P"
+ end
+ execoutput("#{command(:setsebool)} #{persist} #{@resource[:name]} #{new}")
+ return :file_changed
+ end
+
+ # Required workaround, since SELinux policy prevents setsebool
+ # from writing to any files, even tmp, preventing the standard
+ # 'setsebool("...")' construct from working.
+
+ def execoutput (cmd)
+ output = ''
+ begin
+ execpipe(cmd) do |out|
+ output = out.readlines.join('').chomp!
+ end
+ rescue Puppet::ExecutionFailure
+ raise Puppet::ExecutionFailure, output.split("\n")[0]
+ end
+ return output
+ end
+end
diff --git a/lib/puppet/provider/selmodule/semodule.rb b/lib/puppet/provider/selmodule/semodule.rb
new file mode 100644
index 000000000..498136691
--- /dev/null
+++ b/lib/puppet/provider/selmodule/semodule.rb
@@ -0,0 +1,143 @@
+Puppet::Type.type(:selmodule).provide(:semodule) do
+ desc "Manage SELinux policy modules using the semodule binary."
+
+ commands :semodule => "/usr/sbin/semodule"
+
+ def create
+ begin
+ execoutput("#{command(:semodule)} --install #{selmod_name_to_filename}")
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not load policy module: %s" % [detail];
+ end
+ return :true
+ end
+
+ def destroy
+ begin
+ execoutput("#{command(:semodule)} --remove #{@resource[:name]}")
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not remove policy module: %s" % [detail];
+ end
+ end
+
+ def exists?
+ self.debug "Checking for module #{@resource[:name]}"
+ execpipe("#{command(:semodule)} --list") do |out|
+ out.each do |line|
+ if line =~ /#{@resource[:name]}\b/
+ return :true
+ end
+ end
+ end
+ return nil
+ end
+
+ def syncversion
+ self.debug "Checking syncversion on #{@resource[:name]}"
+
+ loadver = selmodversion_loaded
+
+ if(loadver) then
+ filever = selmodversion_file
+ if (filever == loadver) then
+ return :true
+ end
+ end
+ return :false
+ end
+
+ def syncversion= (dosync)
+ begin
+ execoutput("#{command(:semodule)} --upgrade #{selmod_name_to_filename}")
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not upgrade policy module: %s" % [detail];
+ end
+ end
+
+ # Helper functions
+
+ def execoutput (cmd)
+ output = ''
+ begin
+ execpipe(cmd) do |out|
+ output = out.readlines.join('').chomp!
+ end
+ rescue Puppet::ExecutionFailure
+ raise Puppet::ExecutionFailure, output.split("\n")[0]
+ end
+ return output
+ end
+
+ def selmod_name_to_filename
+ if @resource[:selmodulepath]
+ return @resource[:selmodulepath]
+ else
+ return "#{@resource[:selmoduledir]}/#{@resource[:name]}.pp"
+ end
+ end
+
+ def selmod_readnext (handle)
+ len = handle.read(4).unpack('L')[0]
+ return handle.read(len)
+ end
+
+ def selmodversion_file
+ magic = 0xF97CFF8F
+
+ filename = selmod_name_to_filename
+ mod = File.new(filename, "r")
+
+ (hdr, ver, numsec) = mod.read(12).unpack('LLL')
+
+ if hdr != magic
+ raise Puppet::Error, "Found #{hdr} instead of magic #{magic} in #{filename}"
+ end
+
+ if ver != 1
+ raise Puppet::Error, "Unknown policy file version #{ver} in #{filename}"
+ end
+
+ # Read through (and throw away) the file section offsets, and also
+ # the magic header for the first section.
+
+ mod.read((numsec + 1) * 4)
+
+ ## Section 1 should be "SE Linux Module"
+
+ selmod_readnext(mod)
+ selmod_readnext(mod)
+
+ # Skip past the section headers
+ mod.read(14)
+
+ # Module name
+ selmod_readnext(mod)
+
+ # At last! the version
+
+ v = selmod_readnext(mod)
+
+ self.debug "file version #{v}"
+ return v
+ end
+
+ def selmodversion_loaded
+ lines = ()
+ begin
+ execpipe("#{command(:semodule)} --list") do |output|
+ lines = output.readlines
+ lines.each do |line|
+ line.chomp!
+ bits = line.split
+ if bits[0] == @resource[:name] then
+ self.debug "load version #{bits[1]}"
+ return bits[1]
+ end
+ end
+ end
+ rescue Puppet::ExecutionFailure
+ raise Puppet::ExecutionFailure, "Could not list policy modules: %s" % [lines.join(' ').chomp!]
+ end
+ return nil
+ end
+end
diff --git a/lib/puppet/provider/service/redhat.rb b/lib/puppet/provider/service/redhat.rb
index d26f76ebd..faa75476d 100755
--- a/lib/puppet/provider/service/redhat.rb
+++ b/lib/puppet/provider/service/redhat.rb
@@ -6,7 +6,7 @@ Puppet::Type.type(:service).provide :redhat, :parent => :init do
commands :chkconfig => "/sbin/chkconfig", :service => "/sbin/service"
- defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos]
+ defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos, :sles]
def self.defpath
superclass.defpath
diff --git a/lib/puppet/provider/ssh_authorized_key/parsed.rb b/lib/puppet/provider/ssh_authorized_key/parsed.rb
index 602e6dd1b..5411a1fb8 100644
--- a/lib/puppet/provider/ssh_authorized_key/parsed.rb
+++ b/lib/puppet/provider/ssh_authorized_key/parsed.rb
@@ -30,6 +30,12 @@ Puppet::Type.type(:ssh_authorized_key).provide(:parsed,
end
}
+ record_line :key_v1,
+ :fields => %w{options bits exponent modulus name},
+ :optional => %w{options},
+ :rts => /^\s+/,
+ :match => /^(?:(.+) )?(\d+) (\d+) (\d+)(?: (.+))?$/
+
def prefetch
# This was done in the type class but path expansion was failing for
# not yet existing users, the only workaround I found was to move that
diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb
new file mode 100644
index 000000000..819516dc4
--- /dev/null
+++ b/lib/puppet/provider/user/user_role_add.rb
@@ -0,0 +1,89 @@
+require 'puppet/util/user_attr'
+
+Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
+
+ desc "User management inherits ``useradd`` and adds logic to manage roles on Solaris using roleadd."
+
+ defaultfor :operatingsystem => :solaris
+
+ commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
+ options :home, :flag => "-d", :method => :dir
+ options :comment, :method => :gecos
+ options :groups, :flag => "-G"
+ options :roles, :flag => "-R"
+
+ verify :gid, "GID must be an integer" do |value|
+ value.is_a? Integer
+ end
+
+ verify :groups, "Groups must be comma-separated" do |value|
+ value !~ /\s/
+ end
+
+ has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac
+
+ if Puppet.features.libshadow?
+ has_feature :manages_passwords
+ end
+
+ def user_attributes
+ @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name])
+ end
+
+ def flush
+ @user_attributes = nil
+ end
+
+ def command(cmd)
+ if is_role? or (!exists? and @resource[:ensure] == :role)
+ cmd = ("role_" + cmd.to_s).intern
+ end
+ super(cmd)
+ end
+
+ def is_role?
+ user_attributes and user_attributes[:type] == "role"
+ end
+
+ def run(cmd, msg)
+ begin
+ execute(cmd)
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not %s %s %s: %s" %
+ [msg, @resource.class.name, @resource.name, detail]
+ end
+ end
+
+ def transition(type)
+ cmd = [command(:modify)]
+ cmd << "-K" << "type=#{type}"
+ cmd << @resource[:name]
+ end
+
+ def create
+ if is_role?
+ run(transition("normal"), "transition role to")
+ else
+ run(addcmd, "create")
+ end
+ end
+
+ def destroy
+ run(deletecmd, "delete "+ (is_role? ? "role" : "user"))
+ end
+
+ def create_role
+ if exists? and !is_role?
+ run(transition("role"), "transition user to")
+ else
+ run(addcmd, "create role")
+ end
+ end
+
+ def roles
+ if user_attributes
+ user_attributes[:roles]
+ end
+ end
+end
+
diff --git a/lib/puppet/sslcertificates/support.rb b/lib/puppet/sslcertificates/support.rb
index d95944adc..5ca06721d 100644
--- a/lib/puppet/sslcertificates/support.rb
+++ b/lib/puppet/sslcertificates/support.rb
@@ -133,6 +133,9 @@ module Puppet::SSLCertificates::Support
#return nil unless FileTest.directory?(dir)
raise ArgumentError, "Tried to fix SSL files to a file containing uppercase" unless short.downcase == short
+
+ return false unless File.directory?(dir)
+
real_file = Dir.entries(dir).reject { |f| f =~ /^\./ }.find do |other|
other.downcase == short
end
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index c7a866e2c..7e8654921 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -901,19 +901,31 @@ class Type
# retrieve the current value of all contained properties
def retrieve
- return currentpropvalues
+ return currentpropvalues
end
- # get a hash of the current properties.
- def currentpropvalues(override_value = nil)
- # it's important to use the method here, as it follows the order
- # in which they're defined in the object
- return properties().inject({}) { | prophash, property|
- prophash[property] = override_value.nil? ?
- property.retrieve :
- override_value
- prophash
- }
+ # Get a hash of the current properties. Returns a hash with
+ # the actual property instance as the key and the current value
+ # as the, um, value.
+ def currentpropvalues
+ # It's important to use the 'properties' method here, as it follows the order
+ # in which they're defined in the class. It also guarantees that 'ensure'
+ # is the first property, which is important for skipping 'retrieve' on
+ # all the properties if the resource is absent.
+ ensure_state = false
+ return properties().inject({}) do | prophash, property|
+ if property.name == :ensure
+ ensure_state = property.retrieve
+ prophash[property] = ensure_state
+ else
+ if ensure_state == :absent
+ prophash[property] = :absent
+ else
+ prophash[property] = property.retrieve
+ end
+ end
+ prophash
+ end
end
# Are we running in noop mode?
@@ -1460,8 +1472,6 @@ class Type
raise(ArgumentError, "Cannot add aliases without a catalog") unless @resource.catalog
- @resource.info "Adding aliases %s" % aliases.collect { |a| a.inspect }.join(", ")
-
aliases.each do |other|
if obj = @resource.catalog.resource(@resource.class.name, other)
unless obj.object_id == @resource.object_id
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 2a5e61de8..371571ff3 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -1157,4 +1157,5 @@ module Puppet
require 'puppet/type/file/group'
require 'puppet/type/file/mode'
require 'puppet/type/file/type'
+ require 'puppet/type/file/selcontext' # SELinux file context
end
diff --git a/lib/puppet/type/file/checksum.rb b/lib/puppet/type/file/checksum.rb
index 3be147cb7..27edee13d 100755
--- a/lib/puppet/type/file/checksum.rb
+++ b/lib/puppet/type/file/checksum.rb
@@ -53,6 +53,9 @@ Puppet::Type.type(:file).newproperty(:checksum) do
else
if FileTest.directory?(@resource[:path])
return :time
+ elsif @resource[:source]
+ self.warning("Files with source set must use md5 as checksum. Forcing to md5 from %s for %s" % [ value, @resource[:path] ])
+ return :md5
else
return symbolize(value)
end
@@ -161,6 +164,7 @@ Puppet::Type.type(:file).newproperty(:checksum) do
checktype = :mtime if checktype == :timestamp
checktype = :ctime if checktype == :time
+ self.should = checktype = :md5 if @resource.property(:source)
file ||= @resource[:path]
diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb
index cc482ff31..56883add6 100755
--- a/lib/puppet/type/file/group.rb
+++ b/lib/puppet/type/file/group.rb
@@ -1,6 +1,10 @@
+require 'puppet/util/posix'
+
# Manage file group ownership.
module Puppet
Puppet.type(:file).newproperty(:group) do
+ include Puppet::Util::POSIX
+
require 'etc'
desc "Which group should own the file. Argument can be either group
name or group ID."
@@ -42,32 +46,23 @@ module Puppet
end
end
- def retrieve
- if self.should
- @should = @should.collect do |val|
- unless val.is_a?(Integer)
- if tmp = validgroup?(val)
- val = tmp
- else
- raise "Could not find group %s" % val
- end
- else
- val
- end
+ def insync?(current)
+ @should.each do |value|
+ if value =~ /^\d+$/
+ gid = Integer(value)
+ elsif value.is_a?(String)
+ fail "Could not find group %s" % value unless gid = gid(value)
+ else
+ gid = value
end
- end
- stat = @resource.stat(false)
- unless stat
- return :absent
+ return true if gid == current
end
+ return false
+ end
- # Set our method appropriately, depending on links.
- if stat.ftype == "link" and @resource[:links] != :follow
- @method = :lchown
- else
- @method = :chown
- end
+ def retrieve
+ return :absent unless stat = resource.stat(false)
currentvalue = stat.gid
@@ -84,12 +79,8 @@ module Puppet
# Determine if the group is valid, and if so, return the GID
def validgroup?(value)
- if value =~ /^\d+$/
- value = value.to_i
- end
-
- if gid = Puppet::Util.gid(value)
- return gid
+ if number = gid(value)
+ return number
else
return false
end
@@ -99,32 +90,28 @@ module Puppet
# we'll just let it fail, but we should probably set things up so
# that users get warned if they try to change to an unacceptable group.
def sync
- unless @resource.stat(false)
- stat = @resource.stat(true)
- currentvalue = self.retrieve
-
- unless stat
- self.debug "File '%s' does not exist; cannot chgrp" %
- @resource[:path]
- return nil
- end
+ # Set our method appropriately, depending on links.
+ if resource[:links] == :manage
+ method = :lchown
+ else
+ method = :chown
end
gid = nil
- unless gid = Puppet::Util.gid(self.should)
- raise Puppet::Error, "Could not find group %s" % self.should
+ @should.each do |group|
+ break if gid = validgroup?(group)
end
+ raise Puppet::Error, "Could not find group(s) %s" % @should.join(",") unless gid
+
begin
# set owner to nil so it's ignored
- File.send(@method,nil,gid,@resource[:path])
+ File.send(method, nil, gid, resource[:path])
rescue => detail
- error = Puppet::Error.new( "failed to chgrp %s to %s: %s" %
- [@resource[:path], self.should, detail.message])
+ error = Puppet::Error.new( "failed to chgrp %s to %s: %s" % [resource[:path], gid, detail.message])
raise error
end
return :file_changed
end
end
end
-
diff --git a/lib/puppet/type/file/selcontext.rb b/lib/puppet/type/file/selcontext.rb
new file mode 100644
index 000000000..b2c89e6f8
--- /dev/null
+++ b/lib/puppet/type/file/selcontext.rb
@@ -0,0 +1,87 @@
+# Manage SELinux context of files.
+#
+# This code actually manages three pieces of data in the context.
+#
+# [root@delenn files]# ls -dZ /
+# drwxr-xr-x root root system_u:object_r:root_t /
+#
+# The context of '/' here is 'system_u:object_r:root_t'. This is
+# three seperate fields:
+#
+# system_u is the user context
+# object_r is the role context
+# root_t is the type context
+#
+# All three of these fields are returned in a single string by the
+# output of the stat command, but set individually with the chcon
+# command. This allows the user to specify a subset of the three
+# values while leaving the others alone.
+#
+# See http://www.nsa.gov/selinux/ for complete docs on SELinux.
+
+module Puppet
+ require 'puppet/util/selinux'
+
+ class SELFileContext < Puppet::Property
+ include Puppet::Util::SELinux
+
+ def retrieve
+ unless @resource.stat(false)
+ return :absent
+ end
+ context = self.get_selinux_current_context(@resource[:path])
+ return parse_selinux_context(name, context)
+ end
+
+ def retrieve_default_context(property)
+ unless context = self.get_selinux_default_context(@resource[:path])
+ return nil
+ end
+ property_default = self.parse_selinux_context(property, context)
+ self.debug "Found #{property} default '#{property_default}' for #{@resource[:path]}"
+ return property_default
+ end
+
+ def sync
+ unless @resource.stat(false)
+ stat = @resource.stat(true)
+ unless stat
+ return nil
+ end
+ end
+
+ self.set_selinux_context(@resource[:path], @should, name)
+ return :file_changed
+ end
+ end
+
+ Puppet.type(:file).newproperty(:seluser, :parent => Puppet::SELFileContext) do
+ desc "What the SELinux User context of the file should be."
+
+ @event = :file_changed
+ defaultto { self.retrieve_default_context(:seluser) }
+ end
+
+ Puppet.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do
+ desc "What the SELinux Role context of the file should be."
+
+ @event = :file_changed
+ defaultto { self.retrieve_default_context(:selrole) }
+ end
+
+ Puppet.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do
+ desc "What the SELinux Type context of the file should be."
+
+ @event = :file_changed
+ defaultto { self.retrieve_default_context(:seltype) }
+ end
+
+ Puppet.type(:file).newproperty(:selrange, :parent => Puppet::SELFileContext) do
+ desc "What the SELinux Range context of the file should be."
+
+ @event = :file_changed
+ defaultto { self.retrieve_default_context(:selrange) }
+ end
+
+end
+
diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb
index 2a5ac30da..cb11a60a4 100755
--- a/lib/puppet/type/group.rb
+++ b/lib/puppet/type/group.rb
@@ -118,14 +118,6 @@ module Puppet
defaultto false
end
-
- def retrieve
- if self.provider and @provider.exists?
- return super
- else
- return currentpropvalues(:absent)
- end
- end
end
end
diff --git a/lib/puppet/type/selboolean.rb b/lib/puppet/type/selboolean.rb
new file mode 100644
index 000000000..d12dd3bcb
--- /dev/null
+++ b/lib/puppet/type/selboolean.rb
@@ -0,0 +1,29 @@
+#
+# Simple module for manageing SELinux booleans
+#
+
+module Puppet
+ newtype(:selboolean) do
+ @doc = "Enable or disable SELinux booleans."
+
+ newparam(:name) do
+ desc "The name of the SELinux boolean to be managed."
+ isnamevar
+ end
+
+ newproperty(:value) do
+ desc "Whether the the SELinux boolean should be enabled or disabled. Possible values are ``on`` or ``off``."
+ newvalue(:on)
+ newvalue(:off)
+ end
+
+ newparam(:persistent) do
+ desc "If set true, SELinux booleans will be written to disk and persist accross reboots."
+
+ defaultto :false
+ newvalues(:true, :false)
+ end
+
+ end
+end
+
diff --git a/lib/puppet/type/selmodule.rb b/lib/puppet/type/selmodule.rb
new file mode 100644
index 000000000..1f02912ad
--- /dev/null
+++ b/lib/puppet/type/selmodule.rb
@@ -0,0 +1,50 @@
+#
+# Simple module for manageing SELinux policy modules
+#
+
+Puppet::Type.newtype(:selmodule) do
+ @doc = "Enable or disable SELinux policy modules."
+
+ ensurable
+
+ newparam(:name) do
+ desc "The name of the SELinux policy to be managed."
+ isnamevar
+ end
+
+ newparam(:selmoduledir) do
+
+ desc "The directory to look for the compiled pp module file in.
+ Currently defaults to /usr/share/selinux/targeted"
+
+ defaultto "/usr/share/selinux/targeted"
+ end
+
+ newparam(:selmodulepath) do
+
+ desc "The full path in which to look for the compiled pp
+ module file in. You only need to use this if the module file
+ is not in the directory pointed at by selmoduledir."
+
+ end
+
+ newproperty(:syncversion) do
+
+ desc "If set to 'true', the policy will be reloaded if the
+ version found in the on-disk file differs from the loaded
+ version. If set to 'false' (the default) the the only check
+ that will be made is if the policy is loaded at all or not."
+
+ newvalue(:true)
+ newvalue(:false)
+ end
+
+ autorequire(:file) do
+ if self[:selmodulepath]
+ [self[:selmodulepath]]
+ else
+ ["#{self[:selmoduledir]}/#{self[:name]}.pp"]
+ end
+ end
+end
+
diff --git a/lib/puppet/type/ssh_authorized_key.rb b/lib/puppet/type/ssh_authorized_key.rb
index 1db4a0ac3..4afca1cca 100644
--- a/lib/puppet/type/ssh_authorized_key.rb
+++ b/lib/puppet/type/ssh_authorized_key.rb
@@ -1,6 +1,7 @@
module Puppet
newtype(:ssh_authorized_key) do
- @doc = "Manages ssh authorized keys."
+ @doc = "Manages SSH authorized keys. Currently only type 2 keys are
+ supported."
ensurable
@@ -11,8 +12,7 @@ module Puppet
end
newproperty(:type) do
- desc "The encryption type used. Usually ssh-dss or ssh-rsa for
- SSH version 2. Not used for SSH version 1."
+ desc "The encryption type used: ssh-dss or ssh-rsa."
newvalue("ssh-dss")
newvalue("ssh-rsa")
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 039bcb7cb..29f4880c1 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -1,5 +1,6 @@
require 'etc'
require 'facter'
+require 'puppet/property/list'
module Puppet
newtype(:user) do
@@ -21,6 +22,9 @@ module Puppet
"The provider can modify user passwords, by accepting a password
hash."
+ feature :manages_solaris_rbac,
+ "The provider can manage roles and normal users"
+
newproperty(:ensure, :parent => Puppet::Property::Ensure) do
newvalue(:present, :event => :user_created) do
provider.create
@@ -30,6 +34,10 @@ module Puppet
provider.delete
end
+ newvalue(:role, :event => :role_created, :required_features => :manages_solaris_rbac) do
+ provider.create_role
+ end
+
desc "The basic state that the object should be in."
# If they're talking about the thing at all, they generally want to
@@ -44,30 +52,15 @@ module Puppet
def retrieve
if provider.exists?
- return :present
+ if provider.respond_to?(:is_role?) and provider.is_role?
+ return :role
+ else
+ return :present
+ end
else
return :absent
end
end
-
- # The default 'sync' method only selects among a list of registered
- # values.
- def sync
-# if self.insync?
-# self.info "already in sync"
-# return nil
- #else
- #self.info "%s vs %s" % [self.is.inspect, self.should.inspect]
-# end
- unless self.class.values
- self.devfail "No values defined for %s" %
- self.class.name
- end
-
- # Set ourselves to whatever our should value is.
- self.set(self.should)
- end
-
end
newproperty(:uid) do
@@ -95,50 +88,26 @@ module Puppet
newproperty(:gid) do
desc "The user's primary group. Can be specified numerically or
by name."
-
- def found?
- defined? @found and @found
- end
-
- munge do |gid|
- method = :getgrgid
- case gid
- when String
- if gid =~ /^[-0-9]+$/
- gid = Integer(gid)
- else
- method = :getgrnam
- end
- when Symbol
- unless gid == :auto or gid == :absent
- self.devfail "Invalid GID %s" % gid
- end
- # these are treated specially by sync()
- return gid
- end
- if group = Puppet::Util.gid(gid)
- @found = true
- return group
+ munge do |value|
+ if value.is_a?(String) and value =~ /^[-0-9]+$/
+ Integer(value)
else
- @found = false
- return gid
+ value
end
end
- # *shudder* Make sure that we've looked up the group and gotten
- # an ID for it. Yuck-o.
- def should
- unless defined? @should
- return super
- end
- unless found?
- @should = @should.each { |val|
- next unless val
- Puppet::Util.gid(val)
- }
+ def sync
+ found = false
+ @should.each do |value|
+ if number = Puppet::Util.gid(value)
+ provider.gid = number
+ found = true
+ break
+ end
end
- super
+
+ fail "Could not find group(s) %s" % @should.join(",") unless found
end
end
@@ -168,95 +137,39 @@ module Puppet
end
end
- newproperty(:groups) do
+ newproperty(:groups, :parent => Puppet::Property::List) do
desc "The groups of which the user is a member. The primary
group should not be listed. Multiple groups should be
specified as an array."
- def should_to_s(newvalue)
- self.should
- end
-
- def is_to_s(currentvalue)
- currentvalue.join(",")
- end
-
- # We need to override this because the groups need to
- # be joined with commas
- def should
- current_value = retrieve
-
- unless defined? @should and @should
- return nil
- end
-
- if @resource[:membership] == :inclusive
- return @should.sort.join(",")
- else
- members = @should
- if current_value.is_a?(Array)
- members += current_value
- end
- return members.uniq.sort.join(",")
+ validate do |value|
+ if value =~ /^\d+$/
+ raise ArgumentError, "Group names must be provided, not numbers"
end
- end
-
- def retrieve
- if tmp = provider.groups and tmp != :absent
- return tmp.split(",")
- else
- return :absent
+ if value.include?(",")
+ raise ArgumentError, "Group names must be provided as an array, not as a comma-separated list '%s'" % value
end
end
+ end
- def insync?(is)
- unless defined? @should and @should
- return true
- end
- unless defined? is and is
- return true
- end
- tmp = is
- if is.is_a? Array
- tmp = is.sort.join(",")
- end
+ newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
+ desc "The roles of which the user the user has. The roles should be
+ specified as an array."
- return tmp == self.should
+ def membership
+ :role_membership
end
validate do |value|
if value =~ /^\d+$/
- raise ArgumentError, "Group names must be provided, not numbers"
+ raise ArgumentError, "Role names must be provided, not numbers"
end
if value.include?(",")
- raise ArgumentError, "Group names must be provided as an array, not a comma-separated list"
+ raise ArgumentError, "Role names must be provided as an array, not a comma-separated list"
end
end
end
- # these three properties are all implemented differently on each platform,
- # so i'm disabling them for now
-
- # FIXME Puppet::Property::UserLocked is currently non-functional
- #newproperty(:locked) do
- # desc "The expected return code. An error will be returned if the
- # executed command returns something else."
- #end
-
- # FIXME Puppet::Property::UserExpire is currently non-functional
- #newproperty(:expire) do
- # desc "The expected return code. An error will be returned if the
- # executed command returns something else."
- # @objectaddflag = "-e"
- #end
-
- # FIXME Puppet::Property::UserInactive is currently non-functional
- #newproperty(:inactive) do
- # desc "The expected return code. An error will be returned if the
- # executed command returns something else."
- # @objectaddflag = "-f"
- #end
-
newparam(:name) do
desc "User name. While limitations are determined for
each operating system, it is generally a good idea to keep to
@@ -268,7 +181,17 @@ module Puppet
desc "Whether specified groups should be treated as the only groups
of which the user is a member or whether they should merely
be treated as the minimum membership list."
-
+
+ newvalues(:inclusive, :minimum)
+
+ defaultto :minimum
+ end
+
+ newparam(:role_membership) do
+ desc "Whether specified roles should be treated as the only roles
+ of which the user is a member or whether they should merely
+ be treated as the minimum membership list."
+
newvalues(:inclusive, :minimum)
defaultto :minimum
@@ -338,7 +261,7 @@ module Puppet
current_value = :absent
if absent
- prophash[property] = :absent
+ prophash[property] = :absent
else
current_value = property.retrieve
prophash[property] = current_value
@@ -346,7 +269,6 @@ module Puppet
if property.name == :ensure and current_value == :absent
absent = true
-# next
end
prophash
}
diff --git a/lib/puppet/type/zone.rb b/lib/puppet/type/zone.rb
index 4fd92672c..7601ec47b 100644
--- a/lib/puppet/type/zone.rb
+++ b/lib/puppet/type/zone.rb
@@ -377,7 +377,11 @@ end
result = setstatus(hash)
result
else
- return currentpropvalues(:absent)
+ # Return all properties as absent.
+ return properties().inject({}) do | prophash, property|
+ prophash[property] = :absent
+ prophash
+ end
end
end
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index d6de3e2e1..59f732dae 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -227,7 +227,11 @@ module Util
end
else
x = %x{which #{bin} 2>/dev/null}.chomp
- return x
+ if x == ""
+ return nil
+ else
+ return x
+ end
end
end
module_function :binary
diff --git a/lib/puppet/util/filetype.rb b/lib/puppet/util/filetype.rb
index 8dcb67286..7e799b613 100755
--- a/lib/puppet/util/filetype.rb
+++ b/lib/puppet/util/filetype.rb
@@ -1,8 +1,13 @@
# Basic classes for reading, writing, and emptying files. Not much
# to see here.
+
+require 'puppet/util/selinux'
+
class Puppet::Util::FileType
attr_accessor :loaded, :path, :synced
+ include Puppet::Util::SELinux
+
class << self
attr_accessor :name
include Puppet::Util::ClassGen
@@ -109,6 +114,8 @@ class Puppet::Util::FileType
tf.print text; tf.flush
FileUtils.cp(tf.path, @path)
tf.close
+ # If SELinux is present, we need to ensure the file has its expected context
+ set_selinux_default_context(@path)
end
end
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb
index 8824a8b50..0dfd36dfa 100644
--- a/lib/puppet/util/log.rb
+++ b/lib/puppet/util/log.rb
@@ -1,10 +1,12 @@
require 'syslog'
+require 'puppet/util/tagging'
# Pass feedback to the user. Log levels are modeled after syslog's, and it is
# expected that that will be the most common log destination. Supports
# multiple destinations, one of which is a remote server.
class Puppet::Util::Log
include Puppet::Util
+ include Puppet::Util::Tagging
@levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
@loglevel = 2
@@ -470,12 +472,12 @@ class Puppet::Util::Log
@levels.include?(level)
end
- attr_accessor :level, :message, :time, :tags, :remote
+ attr_accessor :level, :message, :time, :remote
attr_reader :source
def initialize(args)
unless args.include?(:level) && args.include?(:message)
- raise Puppet::DevError, "Puppet::Util::Log called incorrectly"
+ raise ArgumentError, "Puppet::Util::Log called incorrectly"
end
if args[:level].class == String
@@ -483,35 +485,27 @@ class Puppet::Util::Log
elsif args[:level].class == Symbol
@level = args[:level]
else
- raise Puppet::DevError,
- "Level is not a string or symbol: #{args[:level].class}"
+ raise ArgumentError, "Level is not a string or symbol: #{args[:level].class}"
end
- # Just return unless we're actually at a level we should send
- #return unless self.class.sendlevel?(@level)
-
@message = args[:message].to_s
@time = Time.now
- # this should include the host name, and probly lots of other
- # stuff, at some point
- unless self.class.validlevel?(level)
- raise Puppet::DevError, "Invalid message level #{level}"
- end
- if args.include?(:tags)
- @tags = args[:tags]
- end
+ raise ArgumentError, "Invalid log level %s" % level unless self.class.validlevel?(level)
- if args.include?(:source)
- self.source = args[:source]
- else
- @source = "Puppet"
+ if tags = args[:tags]
+ tags.each { |t| self.tag(t) }
end
+ self.source = args[:source] || "Puppet"
+
+ # Tag myself with my log level
+ tag(level)
+
Log.newmessage(self)
end
- # Was the source of this log an object?
+ # Was the source of this log a Puppet resource or parameter?
def objectsource?
if defined? @objectsource and @objectsource
@objectsource
@@ -533,17 +527,11 @@ class Puppet::Util::Log
@objectsource = false
@source = source.to_s
end
- unless defined? @tags and @tags
- if source.respond_to?(:tags)
- @tags = source.tags
- end
+ if source.respond_to?(:tags)
+ source.tags.each { |t| tag(t) }
end
end
- def tagged?(tag)
- @tags.detect { |t| t.to_s == tag.to_s }
- end
-
def to_report
"%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s]
end
@@ -552,5 +540,8 @@ class Puppet::Util::Log
return @message
end
end
-Puppet::Log = Puppet::Util::Log
+# This is for backward compatibility from when we changed the constant to Puppet::Util::Log
+# because the reports include the constant name. Apparently the alias was created in
+# March 2007, should could probably be removed soon.
+Puppet::Log = Puppet::Util::Log
diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb
index ca23aa87f..e6d7678aa 100644
--- a/lib/puppet/util/metric.rb
+++ b/lib/puppet/util/metric.rb
@@ -5,6 +5,8 @@ require 'puppet'
class Puppet::Util::Metric
# Load the library as a feature, so we can test its presence.
+ # It's only used by this class, so there's no reason to move it
+ # to the main feature list.
Puppet.features.add :rrd, :libs => 'RRDtool'
attr_accessor :type, :name, :value, :label
@@ -12,6 +14,15 @@ class Puppet::Util::Metric
attr_writer :basedir
+ # Return a specific value
+ def [](name)
+ if value = @values.find { |v| v[0] == name }
+ return value[2]
+ else
+ return nil
+ end
+ end
+
def basedir
if defined? @basedir
@basedir
@@ -93,11 +104,7 @@ class Puppet::Util::Metric
def initialize(name,label = nil)
@name = name.to_s
- if label
- @label = label
- else
- @label = name.to_s.capitalize.gsub("_", " ")
- end
+ @label = label || labelize(name)
@values = []
end
@@ -107,9 +114,7 @@ class Puppet::Util::Metric
end
def newvalue(name,value,label = nil)
- unless label
- label = name.to_s.capitalize.gsub("_", " ")
- end
+ label ||= labelize(name)
@values.push [name,label,value]
end
@@ -145,7 +150,16 @@ class Puppet::Util::Metric
def values
@values.sort { |a, b| a[1] <=> b[1] }
end
+
+ private
+
+ # Convert a name into a label.
+ def labelize(name)
+ name.to_s.capitalize.gsub("_", " ")
+ end
end
+# This is necessary because we changed the class path in early 2007,
+# and reports directly yaml-dump these metrics, so both client and server
+# have to agree on the class name.
Puppet::Metric = Puppet::Util::Metric
-
diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb
index 9281169ea..b969a041c 100755
--- a/lib/puppet/util/posix.rb
+++ b/lib/puppet/util/posix.rb
@@ -7,10 +7,8 @@ module Puppet::Util::POSIX
# method search_posix_field in the gid and uid methods if a sanity check
# fails
def get_posix_field(space, field, id)
- unless id
- raise ArgumentError, "Did not get id"
- end
- prefix = "get" + space.to_s
+ raise Puppet::DevError, "Did not get id from caller" unless id
+
if id.is_a?(Integer)
if id > Puppet[:maximum_uid].to_i
Puppet.err "Tried to get %s field for silly id %s" % [field, id]
@@ -132,16 +130,16 @@ module Puppet::Util::POSIX
# Get the GID of a given group, provided either a GID or a name
def gid(group)
begin
- group = Integer(group)
+ group = Integer(group)
rescue ArgumentError
- # pass
+ # pass
end
if group.is_a?(Integer)
- name = get_posix_field(:group, :name, group)
+ return nil unless name = get_posix_field(:group, :name, group)
gid = get_posix_field(:group, :gid, name)
check_value = gid
else
- gid = get_posix_field(:group, :gid, group)
+ return nil unless gid = get_posix_field(:group, :gid, group)
name = get_posix_field(:group, :name, gid)
check_value = name
end
@@ -155,16 +153,16 @@ module Puppet::Util::POSIX
# Get the UID of a given user, whether a UID or name is provided
def uid(user)
begin
- user = Integer(user)
+ user = Integer(user)
rescue ArgumentError
- # pass
+ # pass
end
if user.is_a?(Integer)
- name = get_posix_field(:passwd, :name, user)
+ return nil unless name = get_posix_field(:passwd, :name, user)
uid = get_posix_field(:passwd, :uid, name)
check_value = uid
else
- uid = get_posix_field(:passwd, :uid, user)
+ return nil unless uid = get_posix_field(:passwd, :uid, user)
name = get_posix_field(:passwd, :name, uid)
check_value = name
end
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
new file mode 100644
index 000000000..8c1aecf3b
--- /dev/null
+++ b/lib/puppet/util/selinux.rb
@@ -0,0 +1,136 @@
+# Provides utility functions to help interfaces Puppet to SELinux.
+#
+# Currently this is implemented via the command line tools. At some
+# point support should be added to use the new SELinux ruby bindings
+# as that will be faster and more reliable then shelling out when they
+# are available. At this time (2008-09-26) these bindings aren't bundled on
+# any SELinux-using distribution I know of.
+
+module Puppet::Util::SELinux
+
+ def selinux_support?
+ FileTest.exists?("/selinux/enforce")
+ end
+
+ # Retrieve and return the full context of the file. If we don't have
+ # SELinux support or if the stat call fails then return nil.
+ def get_selinux_current_context(file)
+ unless selinux_support?
+ return nil
+ end
+ context = ""
+ begin
+ execpipe("stat -c %C #{file}") do |out|
+ out.each do |line|
+ context << line
+ end
+ end
+ rescue Puppet::ExecutionFailure
+ return nil
+ end
+ context.chomp!
+ # Handle the case that the system seems to have SELinux support but
+ # stat finds unlabled files.
+ if context == "(null)"
+ return nil
+ end
+ return context
+ end
+
+ # Use the matchpathcon command, if present, to return the SELinux context
+ # which the SELinux policy on the system expects the file to have. We can
+ # use this to obtain a good default context. If the command does not
+ # exist or the call fails return nil.
+ #
+ # Note: For this command to work a full, non-relative, filesystem path
+ # should be given.
+ def get_selinux_default_context(file)
+ unless selinux_support?
+ return nil
+ end
+ unless FileTest.executable?("/usr/sbin/matchpathcon")
+ return nil
+ end
+ context = ""
+ begin
+ execpipe("/usr/sbin/matchpathcon #{file}") do |out|
+ out.each do |line|
+ context << line
+ end
+ end
+ rescue Puppet::ExecutionFailure
+ return nil
+ end
+ # For a successful match, matchpathcon returns two fields separated by
+ # a variable amount of whitespace. The second field is the full context.
+ context = context.split(/\s/)[1]
+ return context
+ end
+
+ # Take the full SELinux context returned from the tools and parse it
+ # out to the three (or four) component parts. Supports :seluser, :selrole,
+ # :seltype, and on systems with range support, :selrange.
+ def parse_selinux_context(component, context)
+ if context.nil? or context == "unlabeled"
+ return nil
+ end
+ unless context =~ /^([a-z0-9_]+):([a-z0-9_]+):([a-z0-9_]+)(?::([a-zA-Z0-9:,._-]+))?/
+ raise Puppet::Error, "Invalid context to parse: #{context}"
+ end
+ ret = {
+ :seluser => $1,
+ :selrole => $2,
+ :seltype => $3,
+ :selrange => $4,
+ }
+ return ret[component]
+ end
+
+ # This updates the actual SELinux label on the file. You can update
+ # only a single component or update the entire context. It is just a
+ # wrapper around the chcon command.
+ def set_selinux_context(file, value, component = false)
+ unless selinux_support?
+ return nil
+ end
+ case component
+ when :seluser
+ flag = "-u"
+ when :selrole
+ flag = "-r"
+ when :seltype
+ flag = "-t"
+ when :selrange
+ flag = "-l"
+ else
+ flag = ""
+ end
+
+ Puppet.debug "Running chcon #{flag} #{value} #{file}"
+ retval = system("chcon #{flag} #{value} #{file}")
+ unless retval
+ error = Puppet::Error.new("failed to chcon %s" % [@resource[:path]])
+ raise error
+ return false
+ end
+ return true
+ end
+
+ # Since this call relies on get_selinux_default_context it also needs a
+ # full non-relative path to the file. Fortunately, that seems to be all
+ # Puppet uses. This will set the file's SELinux context to the policy's
+ # default context (if any) if it differs from the context currently on
+ # the file.
+ def set_selinux_default_context(file)
+ new_context = get_selinux_default_context(file)
+ unless new_context
+ return nil
+ end
+ cur_context = get_selinux_current_context(file)
+ if new_context != cur_context
+ set_selinux_context(file, new_context)
+ return new_context
+ end
+ return nil
+ end
+end
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index a8eb09049..1e49a3ada 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -114,12 +114,14 @@ class Puppet::Util::Settings
end
# Do variable interpolation on the value.
- def convert(value)
+ def convert(value, environment = nil)
return value unless value
return value unless value.is_a? String
newval = value.gsub(/\$(\w+)|\$\{(\w+)\}/) do |value|
varname = $2 || $1
- if pval = self.value(varname)
+ if varname == "environment" and environment
+ environment
+ elsif pval = self.value(varname)
pval
else
raise Puppet::DevError, "Could not find value for %s" % value
@@ -781,7 +783,7 @@ Generated on #{Time.now}.
val = @config[param].default if val.nil?
# Convert it if necessary
- val = convert(val)
+ val = convert(val, environment)
# And cache it
@cache[environment||"none"][param] = val
diff --git a/lib/puppet/util/user_attr.rb b/lib/puppet/util/user_attr.rb
new file mode 100644
index 000000000..db8fb81b9
--- /dev/null
+++ b/lib/puppet/util/user_attr.rb
@@ -0,0 +1,21 @@
+class UserAttr
+ def self.get_attributes_by_name(name)
+ attributes = nil
+
+ File.readlines('/etc/user_attr').each do |line|
+ next if line =~ /^#/
+
+ token = line.split(':')
+
+ if token[0] == name
+ attributes = {:name => name}
+ token[4].split(';').each do |attr|
+ key_value = attr.split('=')
+ attributes[key_value[0].intern] = key_value[1].strip
+ end
+ break
+ end
+ end
+ return attributes
+ end
+end
diff --git a/spec/integration/provider/package.rb b/spec/integration/provider/package.rb
new file mode 100755
index 000000000..24a196266
--- /dev/null
+++ b/spec/integration/provider/package.rb
@@ -0,0 +1,26 @@
+#!/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 "Package Provider" do
+ Puppet::Type.type(:package).providers.each do |name|
+ provider = Puppet::Type.type(:package).provider(name)
+
+ describe name do
+ confine "Provider %s is not suitable" % name => provider.suitable?
+
+ it "should fail when asked to install an invalid package" do
+ pending("This test hangs forever with recent versions of RubyGems") if provider.name == :gem
+ pkg = Puppet::Type.newpackage :name => "nosuch%s" % provider.name.to_s, :provider => provider.name
+ lambda { pkg.provider.install }.should raise_error
+ end
+
+ it "should be able to get a list of existing packages" do
+ provider.instances.each do |package|
+ package.should be_instance_of(provider)
+ package.properties[:provider].should == provider.name
+ end
+ end
+ end
+ end
+end
diff --git a/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb
index 0b4a5abdb..27cd6b3df 100644
--- a/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb
+++ b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb
@@ -15,7 +15,10 @@ module Spec
prepare
success = true
example_groups.each do |example_group|
- next unless example_group.runnable?
+ unless example_group.runnable?
+ warn "Skipping unsuitable example group %s: %s" % [example_group.description, example_group.messages.join(", ")]
+ next
+ end
success = success & example_group.run
end
return success
diff --git a/spec/monkey_patches/alias_should_to_must.rb b/spec/monkey_patches/alias_should_to_must.rb
new file mode 100644
index 000000000..35d3342f2
--- /dev/null
+++ b/spec/monkey_patches/alias_should_to_must.rb
@@ -0,0 +1,5 @@
+class Object
+ # This is necessary because the RAL has a 'should'
+ # method.
+ alias :must :should
+end
diff --git a/spec/unit/file_serving/fileset.rb b/spec/unit/file_serving/fileset.rb
index 2cd3e83dd..18ac1b445 100755
--- a/spec/unit/file_serving/fileset.rb
+++ b/spec/unit/file_serving/fileset.rb
@@ -176,6 +176,15 @@ describe Puppet::FileServing::Fileset, " when recursing" do
@fileset.links = :manage
@fileset.files.sort.should == @files.sort
end
+
+ it "should succeed when paths have regexp significant characters" do
+ @path = "/my/path/rV1x2DafFr0R6tGG+1bbk++++TM"
+ File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+ @fileset = Puppet::FileServing::Fileset.new(@path)
+ mock_dir_structure(@path)
+ @fileset.recurse = true
+ @fileset.files.sort.should == @files.sort
+ end
end
describe Puppet::FileServing::Fileset, " when following links that point to missing files" do
diff --git a/spec/unit/file_serving/metadata.rb b/spec/unit/file_serving/metadata.rb
index 9743370c1..60fcbc3d3 100755
--- a/spec/unit/file_serving/metadata.rb
+++ b/spec/unit/file_serving/metadata.rb
@@ -99,6 +99,14 @@ describe Puppet::FileServing::Metadata, " when collecting attributes" do
@metadata.checksum.should == "{md5}" + @checksum
end
+ it "should give a mtime checksum when checksum_type is set" do
+ time = Time.now
+ @metadata.checksum_type = "mtime"
+ @metadata.expects(:mtime_file).returns(@time)
+ @metadata.collect_attributes
+ @metadata.checksum.should == "{mtime}" + @time.to_s
+ end
+
it "should produce tab-separated mode, type, owner, group, and checksum for xmlrpc" do
@metadata.attributes_with_tabs.should == "#{0755.to_s}\tfile\t10\t20\t{md5}#{@checksum}"
end
@@ -109,14 +117,22 @@ describe Puppet::FileServing::Metadata, " when collecting attributes" do
@stat.stubs(:ftype).returns("directory")
@time = Time.now
@metadata.expects(:ctime_file).returns(@time)
- @metadata.collect_attributes
end
it "should only use checksums of type 'ctime' for directories" do
+ @metadata.collect_attributes
+ @metadata.checksum.should == "{ctime}" + @time.to_s
+ end
+
+ it "should only use checksums of type 'ctime' for directories even if checksum_type set" do
+ @metadata.checksum_type = "mtime"
+ @metadata.expects(:mtime_file).never
+ @metadata.collect_attributes
@metadata.checksum.should == "{ctime}" + @time.to_s
end
it "should produce tab-separated mode, type, owner, group, and checksum for xmlrpc" do
+ @metadata.collect_attributes
@metadata.attributes_with_tabs.should == "#{0755.to_s}\tdirectory\t10\t20\t{ctime}#{@time.to_s}"
end
end
diff --git a/spec/unit/module.rb b/spec/unit/module.rb
index 4d66550b5..a6608fc1b 100755
--- a/spec/unit/module.rb
+++ b/spec/unit/module.rb
@@ -89,6 +89,19 @@ describe Puppet::Module, " when searching for templates" do
Puppet::Module.find_template("mymod/mytemplate").should == "/my/templates/mymod/mytemplate"
end
+ it "should raise an error if no valid templatedir exists" do
+ Puppet::Module.stubs(:templatepath).with(nil).returns(nil)
+ lambda { Puppet::Module.find_template("mytemplate") }.should raise_error
+ end
+
+ it "should not raise an error if no valid templatedir exists and the template exists in a module" do
+ Puppet::Module.stubs(:templatepath).with(nil).returns(nil)
+ Puppet[:modulepath] = "/one:/two"
+ File.stubs(:directory?).returns(true)
+ File.stubs(:exists?).returns(true)
+ Puppet::Module.find_template("mymod/mytemplate").should == "/one/mymod/templates/mytemplate"
+ end
+
it "should use the main templatedir if no module is found" do
Puppet::Module.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Module.expects(:find).with("mymod", nil).returns(nil)
diff --git a/spec/unit/network/handler/fileserver.rb b/spec/unit/network/handler/fileserver.rb
new file mode 100644
index 000000000..4ba8e712d
--- /dev/null
+++ b/spec/unit/network/handler/fileserver.rb
@@ -0,0 +1,179 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/network/handler/fileserver'
+
+
+describe Puppet::Network::Handler::FileServer do
+ require 'tmpdir'
+
+ def create_file(filename)
+ File.open(filename, "w") { |f| f.puts filename}
+ end
+
+ def create_nested_file()
+ dirname = File.join(@basedir, "nested_dir")
+ Dir.mkdir(dirname)
+ file = File.join(dirname, "nested_dir_file")
+ create_file(file)
+ end
+
+ before do
+ @basedir = File.join(Dir.tmpdir(), "test_network_handler")
+ Dir.mkdir(@basedir)
+ @file = File.join(@basedir, "aFile")
+ @link = File.join(@basedir, "aLink")
+ create_file(@file)
+ @mount = Puppet::Network::Handler::FileServer::Mount.new("some_path", @basedir)
+ end
+
+ it "should list a single directory" do
+ @mount.list("/", false, false).should == [["/", "directory"]]
+ end
+
+ it "should list a file within a directory when given the file path" do
+ @mount.list("/aFile", false, "false").should == [["/", "file"]]
+ end
+
+ it "should list a file within a directory when given the file path with recursion" do
+ @mount.list("/aFile", true, "false").should == [["/", "file"]]
+ end
+
+ it "should return nil for a non-existent path" do
+ @mount.list("/no_such_file", false, false).should be(nil)
+ end
+
+ it "should list a symbolic link as a file when given the link path" do
+ File.symlink(@file, @link)
+ @mount.list("/aLink", false, false).should == [["/", "file"]]
+ end
+
+ it "should return nil for a dangling symbolic link when given the link path" do
+ File.symlink("/some/where", @link)
+ @mount.list("/aLink", false, false).should be(nil)
+ end
+
+ it "should list directory contents of a flat directory structure when asked to recurse" do
+ list = @mount.list("/", true, false)
+ list.should include(["/aFile", "file"])
+ list.should include(["/", "directory"])
+ list.should have(2).items
+ end
+
+ it "should list the contents of a nested directory" do
+ create_nested_file()
+ list = @mount.list("/", true, false)
+ list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ,
+ ["/nested_dir", "directory"], ["/nested_dir/nested_dir_file", "file"]].sort
+ end
+
+ it "should list the contents of a directory ignoring files that match" do
+ create_nested_file()
+ list = @mount.list("/", true, "*File")
+ list.sort.should == [ ["/", "directory"] ,
+ ["/nested_dir", "directory"], ["/nested_dir/nested_dir_file", "file"]].sort
+ end
+
+ it "should list the contents of a directory ignoring directories that match" do
+ create_nested_file()
+ list = @mount.list("/", true, "*nested_dir")
+ list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ].sort
+ end
+
+ it "should list the contents of a directory ignoring all ignore patterns that match" do
+ create_nested_file()
+ list = @mount.list("/", true, ["*File" , "*nested_dir"])
+ list.should == [ ["/", "directory"] ]
+ end
+
+ it "should list the directory when recursing to a depth of zero" do
+ create_nested_file()
+ list = @mount.list("/", 0, false)
+ list.should == [["/", "directory"]]
+ end
+
+ it "should list the base directory and files and nested directory to a depth of one" do
+ create_nested_file()
+ list = @mount.list("/", 1, false)
+ list.sort.should == [ ["/aFile", "file"], ["/nested_dir", "directory"], ["/", "directory"] ].sort
+ end
+
+ it "should list the base directory and files and nested directory to a depth of two" do
+ create_nested_file()
+ list = @mount.list("/", 2, false)
+ list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ,
+ ["/nested_dir", "directory"], ["/nested_dir/nested_dir_file", "file"]].sort
+ end
+
+ it "should list the base directory and files and nested directory to a depth greater than the directory structure" do
+ create_nested_file()
+ list = @mount.list("/", 42, false)
+ list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ,
+ ["/nested_dir", "directory"], ["/nested_dir/nested_dir_file", "file"]].sort
+ end
+
+ it "should list a valid symbolic link as a file when recursing base dir" do
+ File.symlink(@file, @link)
+ list = @mount.list("/", true, false)
+ list.sort.should == [ ["/", "directory"], ["/aFile", "file"], ["/aLink", "file"] ].sort
+ end
+
+ it "should not error when a dangling symlink is present" do
+ File.symlink("/some/where", @link)
+ lambda { @mount.list("/", true, false) }.should_not raise_error
+ end
+
+ it "should return the directory contents of valid entries when a dangling symlink is present" do
+ File.symlink("/some/where", @link)
+ list = @mount.list("/", true, false)
+ list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ].sort
+ end
+
+ describe Puppet::Network::Handler::FileServer::PluginMount do
+ PLUGINS = Puppet::Network::Handler::FileServer::PLUGINS
+
+ # create a module plugin hierarchy
+ def create_plugin(mod, plugin)
+ dirname = File.join(@basedir, mod)
+ Dir.mkdir(dirname)
+ plugins = File.join(dirname, PLUGINS)
+ Dir.mkdir(plugins)
+ facter = File.join(plugins, plugin)
+ Dir.mkdir(facter)
+ create_file(File.join(facter,"fact.rb"))
+ end
+
+ before :each do
+ @modules = ["one","two"]
+ Puppet::Module.stubs(:all).returns(@modules.collect{ |p| File.join(@basedir,p)} )
+ @modules.each { |m| create_plugin(m, "facter") }
+
+ @modules.each do |p|
+ File.stubs(:directory?).with(File.join(@basedir,p,PLUGINS)).returns(true)
+ end
+
+ @mount = Puppet::Network::Handler::FileServer::PluginMount.new(PLUGINS)
+ @mount.allow("*")
+ end
+
+ it "should list a file within a directory when given the file path with recursion" do
+ @mount.list("facter/fact.rb", true, "false").should == [["/", "file"], ["/", "file"]]
+ end
+
+ it "should return a merged view of all plugins for all modules" do
+ list = @mount.list("facter",true,false)
+ list.should == [["/", "directory"], ["/fact.rb", "file"], ["/", "directory"], ["/fact.rb", "file"]]
+ end
+
+ it "should not fail for inexistant plugins type" do
+ lambda { @mount.list("puppet/parser",true,false) }.should_not raise_error
+ end
+
+ end
+
+ after do
+ FileUtils.rm_rf(@basedir)
+ end
+
+end
diff --git a/spec/unit/network/xmlrpc/client.rb b/spec/unit/network/xmlrpc/client.rb
new file mode 100644
index 000000000..a0a2e77fb
--- /dev/null
+++ b/spec/unit/network/xmlrpc/client.rb
@@ -0,0 +1,13 @@
+#!/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::Network do
+ it "should raise an XMLRPCClientError if a generated class raises a Timeout::Error" do
+ http = mock 'http'
+ Puppet::Network::HttpPool.stubs(:http_instance).returns http
+ file = Puppet::Network::Client.file.new({:Server => "foo.com"})
+ http.stubs(:post2).raises Timeout::Error
+ lambda { file.retrieve }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+end
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
index c6d2e61bf..a72c117ff 100755
--- a/spec/unit/node.rb
+++ b/spec/unit/node.rb
@@ -45,20 +45,15 @@ describe Puppet::Node, "when initializing" do
end
it "should accept an environment value" do
- Puppet.settings.stubs(:value).with(:environments).returns("myenv")
+ Puppet.settings.stubs(:value).with(:environment).returns("myenv")
@node = Puppet::Node.new("testing", :environment => "myenv")
@node.environment.should == "myenv"
end
-
- it "should validate the environment" do
- Puppet.settings.stubs(:value).with(:environments).returns("myenv")
- proc { Puppet::Node.new("testing", :environment => "other") }.should raise_error(ArgumentError)
- end
end
describe Puppet::Node, "when returning the environment" do
before do
- Puppet.settings.stubs(:value).with(:environments).returns("one,two")
+ Puppet.settings.stubs(:value).with(:environment).returns("one,two")
Puppet.settings.stubs(:value).with(:environment).returns("one")
@node = Puppet::Node.new("testnode")
end
@@ -73,16 +68,6 @@ describe Puppet::Node, "when returning the environment" do
Puppet::Node::Environment.expects(:new).returns(env)
@node.environment.should == "myenv"
end
-
- it "should fail if the parameter environment is invalid" do
- @node.parameters = {"environment" => "three"}
- proc { @node.environment }.should raise_error(ArgumentError)
- end
-
- it "should fail if the parameter environment is invalid" do
- @node.parameters = {"environment" => "three"}
- proc { @node.environment }.should raise_error(ArgumentError)
- end
end
describe Puppet::Node, "when merging facts" do
diff --git a/spec/unit/node/environment.rb b/spec/unit/node/environment.rb
index 8433a9877..872c70912 100755
--- a/spec/unit/node/environment.rb
+++ b/spec/unit/node/environment.rb
@@ -5,73 +5,21 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/node/environment'
describe Puppet::Node::Environment do
- it "should provide a list of valid environments" do
- Puppet::Node::Environment.valid.should be_instance_of(Array)
- end
-
- it "should determine its list of valid environments from splitting the :environments setting on commas" do
- Puppet.settings.stubs(:value).with(:environments).returns("one,two")
- Puppet::Node::Environment.valid.collect { |e| e.to_s }.sort.should == %w{one two}.sort
- end
-
- it "should not use an environment when determining the list of valid environments" do
- Puppet.settings.expects(:value).with(:environments).returns("one,two")
- Puppet::Node::Environment.valid
- end
-
- it "should provide a means of identifying invalid environments" do
- Puppet.settings.expects(:value).with(:environments).returns("one,two")
- Puppet::Node::Environment.valid?(:three).should be_false
- end
-
- it "should provide a means of identifying valid environments" do
- Puppet.settings.expects(:value).with(:environments).returns("one,two")
- Puppet::Node::Environment.valid?(:one).should be_true
- end
-
- it "should be used to determine when an environment setting is valid" do
- Puppet.settings.expects(:value).with(:environments).returns("one,two")
- proc { Puppet.settings[:environment] = :three }.should raise_error(ArgumentError)
- end
-
it "should use the default environment if no name is provided while initializing an environment" do
- Puppet.settings.expects(:value).with(:environments).returns("one,two")
Puppet.settings.expects(:value).with(:environment).returns("one")
Puppet::Node::Environment.new().name.should == :one
end
it "should treat environment instances as singletons" do
- Puppet.settings.stubs(:value).with(:environments).returns("one")
Puppet::Node::Environment.new("one").should equal(Puppet::Node::Environment.new("one"))
end
it "should treat an environment specified as names or strings as equivalent" do
- Puppet.settings.stubs(:value).with(:environments).returns("one")
Puppet::Node::Environment.new(:one).should equal(Puppet::Node::Environment.new("one"))
end
-
- it "should fail if an invalid environment instance is asked for" do
- Puppet.settings.stubs(:value).with(:environments).returns("one,two")
- proc { Puppet::Node::Environment.new("three") }.should raise_error(ArgumentError)
- end
-
- it "should consider environments that are empty strings invalid" do
- Puppet::Node::Environment.valid?("").should be_false
- end
-
- it "should fail if a no-longer-valid environment instance is asked for" do
- Puppet.settings.expects(:value).with(:environments).returns("one")
- Puppet::Node::Environment.new("one")
- Puppet.settings.expects(:value).with(:environments).returns("two")
- proc { Puppet::Node::Environment.new("one") }.should raise_error(ArgumentError)
- end
end
describe Puppet::Node::Environment, " when modeling a specific environment" do
- before do
- Puppet.settings.expects(:value).with(:environments).returns("testing")
- end
-
it "should have a method for returning the environment name" do
Puppet::Node::Environment.new("testing").name.should == :testing
end
diff --git a/spec/unit/parser/ast/arithmetic_operator.rb b/spec/unit/parser/ast/arithmetic_operator.rb
new file mode 100755
index 000000000..24d6ad47d
--- /dev/null
+++ b/spec/unit/parser/ast/arithmetic_operator.rb
@@ -0,0 +1,73 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::ArithmeticOperator do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ @one = stub 'lval', :safeevaluate => 1
+ @two = stub 'rval', :safeevaluate => 2
+ end
+
+ it "should evaluate both branches" do
+ lval = stub "lval"
+ lval.expects(:safeevaluate).with(@scope).returns(1)
+ rval = stub "rval"
+ rval.expects(:safeevaluate).with(@scope).returns(2)
+
+ operator = AST::ArithmeticOperator.new :rval => rval, :operator => "+", :lval => lval
+ operator.evaluate(@scope)
+ end
+
+ it "should fail for an unknown operator" do
+ lambda { operator = AST::ArithmeticOperator.new :lval => @one, :operator => "%", :rval => @two }.should raise_error
+ end
+
+ it "should call Puppet::Parser::Scope.number?" do
+ Puppet::Parser::Scope.expects(:number?).with(1).returns(1)
+ Puppet::Parser::Scope.expects(:number?).with(2).returns(2)
+
+ AST::ArithmeticOperator.new(:lval => @one, :operator => "+", :rval => @two).evaluate(@scope)
+ end
+
+
+ %w{ + - * / << >>}.each do |op|
+ it "should call ruby Numeric '#{op}'" do
+ one = stub 'one'
+ two = stub 'two'
+ operator = AST::ArithmeticOperator.new :lval => @one, :operator => op, :rval => @two
+ Puppet::Parser::Scope.stubs(:number?).with(1).returns(one)
+ Puppet::Parser::Scope.stubs(:number?).with(2).returns(two)
+ one.expects(:send).with(op,two)
+ operator.evaluate(@scope)
+ end
+ end
+
+ it "should work even with numbers embedded in strings" do
+ two = stub 'two', :safeevaluate => "2"
+ one = stub 'one', :safeevaluate => "1"
+ operator = AST::ArithmeticOperator.new :lval => two, :operator => "+", :rval => one
+ operator.evaluate(@scope).should == 3
+ end
+
+ it "should work even with floats" do
+ two = stub 'two', :safeevaluate => 2.53
+ one = stub 'one', :safeevaluate => 1.80
+ operator = AST::ArithmeticOperator.new :lval => two, :operator => "+", :rval => one
+ operator.evaluate(@scope).should == 4.33
+ end
+
+ it "should work for variables too" do
+ @scope.expects(:lookupvar).with("one").returns(1)
+ @scope.expects(:lookupvar).with("two").returns(2)
+ one = AST::Variable.new( :value => "one" )
+ two = AST::Variable.new( :value => "two" )
+
+ operator = AST::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ operator.evaluate(@scope).should == 3
+ end
+
+end
diff --git a/spec/unit/parser/ast/boolean_operator.rb b/spec/unit/parser/ast/boolean_operator.rb
new file mode 100755
index 000000000..7304e2a10
--- /dev/null
+++ b/spec/unit/parser/ast/boolean_operator.rb
@@ -0,0 +1,53 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::BooleanOperator do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ @true_ast = AST::Boolean.new( :value => true)
+ @false_ast = AST::Boolean.new( :value => false)
+ end
+
+ it "should evaluate left operand inconditionally" do
+ lval = stub "lval"
+ lval.expects(:safeevaluate).with(@scope).returns("true")
+ rval = stub "rval", :safeevaluate => false
+ rval.expects(:safeevaluate).never
+
+ operator = AST::BooleanOperator.new :rval => rval, :operator => "or", :lval => lval
+ operator.evaluate(@scope)
+ end
+
+ it "should evaluate right 'and' operand only if left operand is true" do
+ lval = stub "lval", :safeevaluate => true
+ rval = stub "rval", :safeevaluate => false
+ rval.expects(:safeevaluate).with(@scope).returns(false)
+ operator = AST::BooleanOperator.new :rval => rval, :operator => "and", :lval => lval
+ operator.evaluate(@scope)
+ end
+
+ it "should evaluate right 'or' operand only if left operand is false" do
+ lval = stub "lval", :safeevaluate => false
+ rval = stub "rval", :safeevaluate => false
+ rval.expects(:safeevaluate).with(@scope).returns(false)
+ operator = AST::BooleanOperator.new :rval => rval, :operator => "or", :lval => lval
+ operator.evaluate(@scope)
+ end
+
+ it "should return true for false OR true" do
+ AST::BooleanOperator.new(:rval => @true_ast, :operator => "or", :lval => @false_ast).evaluate(@scope).should be_true
+ end
+
+ it "should return false for true AND false" do
+ AST::BooleanOperator.new(:rval => @true_ast, :operator => "and", :lval => @false_ast ).evaluate(@scope).should be_false
+ end
+
+ it "should return true for true AND true" do
+ AST::BooleanOperator.new(:rval => @true_ast, :operator => "and", :lval => @true_ast ).evaluate(@scope).should be_true
+ end
+
+end
diff --git a/spec/unit/parser/ast/collexpr.rb b/spec/unit/parser/ast/collexpr.rb
new file mode 100755
index 000000000..e5e6e0d7a
--- /dev/null
+++ b/spec/unit/parser/ast/collexpr.rb
@@ -0,0 +1,92 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::CollExpr do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ describe "when evaluating with two operands" do
+ before :each do
+ @test1 = mock 'test1'
+ @test1.expects(:safeevaluate).with(@scope).returns("test1")
+ @test2 = mock 'test2'
+ @test2.expects(:safeevaluate).with(@scope).returns("test2")
+ end
+
+ it "should evaluate both" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper=>"==")
+ collexpr.evaluate(@scope)
+ end
+
+ it "should produce a textual representation and code of the expression" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper=>"==")
+ result = collexpr.evaluate(@scope)
+ result[0].should == "param_values.value = 'test2' and param_names.name = 'test1'"
+ result[1].should be_an_instance_of(Proc)
+ end
+
+ it "should propagate expression type and form to child if expression themselves" do
+ [@test1, @test2].each do |t|
+ t.expects(:is_a?).returns(true)
+ t.expects(:form).returns(false)
+ t.expects(:type).returns(false)
+ t.expects(:type=)
+ t.expects(:form=)
+ end
+
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper=>"==", :form => true, :type => true)
+ result = collexpr.evaluate(@scope)
+ end
+
+ describe "and when evaluating the produced code" do
+ before :each do
+ @resource = mock 'resource'
+ @resource.expects(:[]).with("test1").at_least(1).returns("test2")
+ end
+
+ it "should evaluate like the original expression for ==" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper => "==")
+ collexpr.evaluate(@scope)[1].call(@resource).should === (@resource["test1"] == "test2")
+ end
+
+ it "should evaluate like the original expression for !=" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper => "!=")
+ collexpr.evaluate(@scope)[1].call(@resource).should === (@resource["test1"] != "test2")
+ end
+ end
+
+ it "should warn if this is an exported collection containing parenthesis (unsupported)" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper=>"==", :parens => true, :form => :exported)
+ Puppet.expects(:warning)
+ collexpr.evaluate(@scope)
+ end
+
+ %w{and or}.each do |op|
+ it "should raise an error if this is an exported collection with #{op} operator (unsupported)" do
+ collexpr = AST::CollExpr.new(:test1 => @test1, :test2 => @test2, :oper=> op, :form => :exported)
+ lambda { collexpr.evaluate(@scope) }.should raise_error(Puppet::ParseError)
+ end
+ end
+ end
+
+ it "should check for array member equality if resource parameter is an array for ==" do
+ array = mock 'array', :safeevaluate => "array"
+ test1 = mock 'test1'
+ test1.expects(:safeevaluate).with(@scope).returns("test1")
+
+ resource = mock 'resource'
+ resource.expects(:[]).with("array").at_least(1).returns(["test1","test2","test3"])
+ collexpr = AST::CollExpr.new(:test1 => array, :test2 => test1, :oper => "==")
+ collexpr.evaluate(@scope)[1].call(resource).should be_true
+ end
+
+ it "should raise an error for invalid operator" do
+ lambda { collexpr = AST::CollExpr.new(:oper=>">") }.should raise_error
+ end
+
+end \ No newline at end of file
diff --git a/spec/unit/parser/ast/comparison_operator.rb b/spec/unit/parser/ast/comparison_operator.rb
new file mode 100755
index 000000000..dbea349f2
--- /dev/null
+++ b/spec/unit/parser/ast/comparison_operator.rb
@@ -0,0 +1,52 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::ComparisonOperator do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ @one = Puppet::Parser::AST::FlatString.new( :value => 1 )
+ @two = Puppet::Parser::AST::FlatString.new( :value => 2 )
+ end
+
+ it "should evaluate both branches" do
+ lval = stub "lval"
+ lval.expects(:safeevaluate).with(@scope)
+ rval = stub "rval"
+ rval.expects(:safeevaluate).with(@scope)
+
+ operator = Puppet::Parser::AST::ComparisonOperator.new :lval => lval, :operator => "==", :rval => rval
+ operator.evaluate(@scope)
+ end
+
+ it "should fail for an unknown operator" do
+ lambda { operator = Puppet::Parser::AST::ComparisonOperator.new :lval => @one, :operator => "or", :rval => @two }.should raise_error
+ end
+
+ %w{< > <= >= ==}.each do |oper|
+ it "should return the result of using '#{oper}' to compare the left and right sides" do
+ one = stub 'one', :safeevaluate => "1"
+ two = stub 'two', :safeevaluate => "2"
+ operator = Puppet::Parser::AST::ComparisonOperator.new :lval => one, :operator => oper, :rval => two
+ operator.evaluate(@scope).should == 1.send(oper,2)
+ end
+ end
+
+ it "should return the result of using '!=' to compare the left and right sides" do
+ one = stub 'one', :safeevaluate => "1"
+ two = stub 'two', :safeevaluate => "2"
+ operator = Puppet::Parser::AST::ComparisonOperator.new :lval => one, :operator => '!=', :rval => two
+ operator.evaluate(@scope).should == true
+ end
+
+ it "should work for variables too" do
+ @scope.expects(:lookupvar).with("one").returns(1)
+ @scope.expects(:lookupvar).with("two").returns(2)
+ one = Puppet::Parser::AST::Variable.new( :value => "one" )
+ two = Puppet::Parser::AST::Variable.new( :value => "two" )
+
+ operator = Puppet::Parser::AST::ComparisonOperator.new :lval => one, :operator => "<", :rval => two
+ operator.evaluate(@scope).should == true
+ end
+
+end
diff --git a/spec/unit/parser/ast/minus.rb b/spec/unit/parser/ast/minus.rb
new file mode 100755
index 000000000..83bd92d0d
--- /dev/null
+++ b/spec/unit/parser/ast/minus.rb
@@ -0,0 +1,36 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::Minus do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ it "should evaluate its argument" do
+ value = stub "value"
+ value.expects(:safeevaluate).with(@scope).returns(123)
+
+ operator = Puppet::Parser::AST::Minus.new :value => value
+ operator.evaluate(@scope)
+ end
+
+ it "should fail if argument is not a string or integer" do
+ array_ast = stub 'array_ast', :safeevaluate => [2]
+ operator = Puppet::Parser::AST::Minus.new :value => array_ast
+ lambda { operator.evaluate(@scope) }.should raise_error
+ end
+
+ it "should work with integer as string" do
+ string = stub 'string', :safeevaluate => "123"
+ operator = Puppet::Parser::AST::Minus.new :value => string
+ operator.evaluate(@scope).should == -123
+ end
+
+ it "should work with integers" do
+ int = stub 'int', :safeevaluate => 123
+ operator = Puppet::Parser::AST::Minus.new :value => int
+ operator.evaluate(@scope).should == -123
+ end
+
+end
diff --git a/spec/unit/parser/ast/nop.rb b/spec/unit/parser/ast/nop.rb
new file mode 100755
index 000000000..5a7132586
--- /dev/null
+++ b/spec/unit/parser/ast/nop.rb
@@ -0,0 +1,20 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::Nop do
+
+ before do
+ @scope = mock 'scope'
+ end
+
+ it "should do nothing on evaluation" do
+ Puppet::Parser::AST.expects(:safeevaluate).never
+ Puppet::Parser::AST::Nop.new({}).evaluate(@scope)
+ end
+
+ it "should not return anything" do
+ Puppet::Parser::AST::Nop.new({}).evaluate(@scope).should be_nil
+ end
+
+end
diff --git a/spec/unit/parser/ast/not.rb b/spec/unit/parser/ast/not.rb
new file mode 100755
index 000000000..0fe2deddd
--- /dev/null
+++ b/spec/unit/parser/ast/not.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::Not do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ @true_ast = Puppet::Parser::AST::Boolean.new( :value => true)
+ @false_ast = Puppet::Parser::AST::Boolean.new( :value => false)
+ end
+
+ it "should evaluate its child expression" do
+ val = stub "val"
+ val.expects(:safeevaluate).with(@scope)
+
+ operator = Puppet::Parser::AST::Not.new :value => val
+ operator.evaluate(@scope)
+ end
+
+ it "should return true for ! false" do
+ operator = Puppet::Parser::AST::Not.new :value => @false_ast
+ operator.evaluate(@scope).should == true
+ end
+
+ it "should return false for ! true" do
+ operator = Puppet::Parser::AST::Not.new :value => @true_ast
+ operator.evaluate(@scope).should == false
+ end
+
+end
diff --git a/spec/unit/parser/ast/resource_override.rb b/spec/unit/parser/ast/resource_override.rb
new file mode 100755
index 000000000..3fbeb323c
--- /dev/null
+++ b/spec/unit/parser/ast/resource_override.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::ResourceOverride do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @compiler = stub 'compiler'
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
+ @params = AST::ASTArray.new({})
+ @compiler.stubs(:add_override)
+ end
+
+ it "should evaluate the overriden object" do
+ klass = stub 'klass', :title => "title", :type => "type"
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns(klass)
+ AST::ResourceOverride.new(:object => object, :params => @params ).evaluate(@scope)
+ end
+
+ it "should tell the compiler to override the resource with our own" do
+ @compiler.expects(:add_override)
+
+ klass = stub 'klass', :title => "title", :type => "one"
+ object = mock 'object', :safeevaluate => klass
+ AST::ResourceOverride.new(:object => object , :params => @params).evaluate(@scope)
+ end
+
+ it "should return the overriden resource directly when called with one item" do
+ klass = stub 'klass', :title => "title", :type => "one"
+ object = mock 'object', :safeevaluate => klass
+ override = AST::ResourceOverride.new(:object => object , :params => @params).evaluate(@scope)
+ override.should be_an_instance_of(Puppet::Parser::Resource)
+ override.title.should == "title"
+ override.type.should == "One"
+ end
+
+ it "should return an array of overriden resources when called with an array of titles" do
+ klass1 = stub 'klass1', :title => "title1", :type => "one"
+ klass2 = stub 'klass2', :title => "title2", :type => "one"
+
+ object = mock 'object', :safeevaluate => [klass1,klass2]
+
+ override = AST::ResourceOverride.new(:object => object , :params => @params).evaluate(@scope)
+ override.should have(2).elements
+ override.each {|o| o.should be_an_instance_of(Puppet::Parser::Resource) }
+ end
+
+end \ No newline at end of file
diff --git a/spec/unit/parser/ast/resource_reference.rb b/spec/unit/parser/ast/resource_reference.rb
new file mode 100755
index 000000000..e4b7c763b
--- /dev/null
+++ b/spec/unit/parser/ast/resource_reference.rb
@@ -0,0 +1,63 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::ResourceReference do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ def newref(title, type)
+ title = stub 'title', :safeevaluate => title
+ ref = AST::ResourceReference.new(:type => type, :title => title)
+ end
+
+ it "should evaluate correctly reference to builtin types" do
+ newref("/tmp/yay", "File").evaluate(@scope).to_s.should == "File[/tmp/yay]"
+ end
+
+ %{ "one::two" "one-two"}.each do |type|
+ it "should evaluate correctly reference to define" do
+ klass = stub 'klass', :title => "three", :classname => type
+ @scope.stubs(:finddefine).returns(klass)
+
+ newref("three", type).evaluate(@scope).to_ref.should == Puppet::Parser::Resource::Reference.new( :type => type, :title => "three" ).to_ref
+ end
+ end
+
+ it "should be able to call qualified_class" do
+ klass = stub 'klass', :title => "three", :classname => "one"
+ @scope.expects(:findclass).with("one").returns(klass)
+ newref("three","class").qualified_class(@scope,"one").should == "one"
+ end
+
+ it "should be able to find qualified classes when evaluating" do
+ klass = stub 'klass', :title => "one", :classname => "one"
+ @scope.stubs(:findclass).returns(klass)
+
+ evaled = newref("one", "class").evaluate(@scope)
+ evaled.type.should == "Class"
+ evaled.title.should == "one"
+ end
+
+ it "should return an array of reference if given an array of titles" do
+ titles = mock 'titles', :safeevaluate => ["title1","title2"]
+ ref = AST::ResourceReference.new( :title => titles, :type => "Resource" )
+ ref.stubs(:qualified_type).with(@scope).returns("Resource")
+
+ ref.evaluate(@scope).should have(2).elements
+ end
+
+ it "should qualify class of all titles for Class resource references" do
+ titles = mock 'titles', :safeevaluate => ["title1","title2"]
+ ref = AST::ResourceReference.new( :title => titles, :type => "Class" )
+ ref.expects(:qualified_class).with(@scope,"title1").returns("class")
+ ref.expects(:qualified_class).with(@scope,"title2").returns("class")
+
+ ref.evaluate(@scope)
+ end
+
+end \ No newline at end of file
diff --git a/spec/unit/parser/lexer.rb b/spec/unit/parser/lexer.rb
index fed1ade7d..3b0df96a9 100755
--- a/spec/unit/parser/lexer.rb
+++ b/spec/unit/parser/lexer.rb
@@ -4,6 +4,27 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/parser/lexer'
+describe Puppet::Parser::Lexer do
+ describe "when reading strings" do
+ before { @lexer = Puppet::Parser::Lexer.new }
+ it "should increment the line count for every carriage return in the string" do
+ @lexer.line = 10
+ @lexer.string = "this\nis\natest'"
+ @lexer.slurpstring("'")
+
+ @lexer.line.should == 12
+ end
+
+ it "should not increment the line count for escapes in the string" do
+ @lexer.line = 10
+ @lexer.string = "this\\nis\\natest'"
+ @lexer.slurpstring("'")
+
+ @lexer.line.should == 10
+ end
+ end
+end
+
describe Puppet::Parser::Lexer::Token do
before do
@token = Puppet::Parser::Lexer::Token.new(%r{something}, :NAME)
@@ -136,7 +157,13 @@ describe Puppet::Parser::Lexer::TOKENS do
:BACKSLASH => '\\',
:FARROW => '=>',
:PARROW => '+>',
- :APPENDS => '+='
+ :APPENDS => '+=',
+ :PLUS => '+',
+ :MINUS => '-',
+ :DIV => '/',
+ :TIMES => '*',
+ :LSHIFT => '<<',
+ :RSHIFT => '>>',
}.each do |name, string|
it "should have a token named #{name.to_s}" do
Puppet::Parser::Lexer::TOKENS[name].should_not be_nil
@@ -213,10 +240,34 @@ describe Puppet::Parser::Lexer::TOKENS[:NAME] do
end
describe Puppet::Parser::Lexer::TOKENS[:NUMBER] do
- before { @token = Puppet::Parser::Lexer::TOKENS[:NUMBER] }
+ before do
+ @token = Puppet::Parser::Lexer::TOKENS[:NUMBER]
+# @regex = Regexp.new('^'+@token.regex.source+'$')
+ @regex = @token.regex
+ end
it "should match against numeric terms" do
- @token.regex.should =~ "2982383139"
+ @regex.should =~ "2982383139"
+ end
+
+ it "should match against float terms" do
+ @regex.should =~ "29823.235"
+ end
+
+ it "should match against hexadecimal terms" do
+ @regex.should =~ "0xBEEF0023"
+ end
+
+ it "should match against float with exponent terms" do
+ @regex.should =~ "10e23"
+ end
+
+ it "should match against float terms with negative exponents" do
+ @regex.should =~ "10e-23"
+ end
+
+ it "should match against float terms with fractional parts and exponent" do
+ @regex.should =~ "1.234e23"
end
it "should return the NAME token and the value" do
diff --git a/spec/unit/parser/parser.rb b/spec/unit/parser/parser.rb
index 94b19be40..c0d22a2cc 100755
--- a/spec/unit/parser/parser.rb
+++ b/spec/unit/parser/parser.rb
@@ -8,6 +8,7 @@ describe Puppet::Parser do
before :each do
@parser = Puppet::Parser::Parser.new :environment => "development"
+ @true_ast = AST::Boolean.new :value => true
end
describe "when parsing append operator" do
@@ -31,4 +32,114 @@ describe Puppet::Parser do
end
end
-end
+
+ describe Puppet::Parser, "when parsing 'if'" do
+ it "not, it should create the correct ast objects" do
+ AST::Not.expects(:new).with { |h| h[:value].is_a?(AST::Boolean) }
+ @parser.parse("if ! true { $var = 1 }")
+
+ end
+
+ it "boolean operation, it should create the correct ast objects" do
+ AST::BooleanOperator.expects(:new).with {
+ |h| h[:rval].is_a?(AST::Boolean) and h[:lval].is_a?(AST::Boolean) and h[:operator]=="or"
+ }
+ @parser.parse("if true or true { $var = 1 }")
+
+ end
+
+ it "comparison operation, it should create the correct ast objects" do
+ AST::ComparisonOperator.expects(:new).with {
+ |h| h[:lval].is_a?(AST::Name) and h[:rval].is_a?(AST::Name) and h[:operator]=="<"
+ }
+ @parser.parse("if 1 < 2 { $var = 1 }")
+
+ end
+
+ end
+
+ describe Puppet::Parser, "when parsing if complex expressions" do
+ it "should create a correct ast tree" do
+ AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(AST::Name) and h[:lval].is_a?(AST::Name) and h[:operator]==">"
+ }.returns("whatever")
+ AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(AST::Name) and h[:lval].is_a?(AST::Name) and h[:operator]=="=="
+ }.returns("whatever")
+ AST::BooleanOperator.expects(:new).with {
+ |h| h[:rval]=="whatever" and h[:lval]=="whatever" and h[:operator]=="and"
+ }
+ @parser.parse("if (1 > 2) and (1 == 2) { $var = 1 }")
+ end
+
+ it "should raise an error on incorrect expression" do
+ lambda { @parser.parse("if (1 > 2 > ) or (1 == 2) { $var = 1 }") }.should raise_error
+ end
+
+ end
+
+ describe Puppet::Parser, "when parsing resource references" do
+
+ it "should not raise syntax errors" do
+ lambda { @parser.parse('exec { test: param => File["a"] }') }.should_not raise_error
+ end
+
+ it "should not raise syntax errors with multiple references" do
+ lambda { @parser.parse('exec { test: param => File["a","b"] }') }.should_not raise_error
+ end
+
+ it "should create an AST::ResourceReference" do
+ AST::Resource.stubs(:new)
+ AST::ResourceReference.expects(:new).with { |arg|
+ arg[:line]==1 and arg[:type]=="File" and arg[:title].is_a?(AST::ASTArray)
+ }
+ @parser.parse('exec { test: command => File["a","b"] }')
+ end
+ end
+
+ describe Puppet::Parser, "when parsing resource overrides" do
+
+ it "should not raise syntax errors" do
+ lambda { @parser.parse('Resource["title"] { param => value }') }.should_not raise_error
+ end
+
+ it "should not raise syntax errors with multiple overrides" do
+ lambda { @parser.parse('Resource["title1","title2"] { param => value }') }.should_not raise_error
+ end
+
+ it "should create an AST::ResourceOverride" do
+ AST::ResourceOverride.expects(:new).with { |arg|
+ arg[:line]==1 and arg[:object].is_a?(AST::ResourceReference) and arg[:params].is_a?(AST::ResourceParam)
+ }
+ @parser.parse('Resource["title1","title2"] { param => value }')
+ end
+
+ end
+
+ describe Puppet::Parser, "when parsing if statements" do
+
+ it "should not raise errors with empty if" do
+ lambda { @parser.parse("if true { }") }.should_not raise_error
+ end
+
+ it "should not raise errors with empty else" do
+ lambda { @parser.parse("if false { notice('if') } else { }") }.should_not raise_error
+ end
+
+ it "should not raise errors with empty if and else" do
+ lambda { @parser.parse("if false { } else { }") }.should_not raise_error
+ end
+
+ it "should create a nop node for empty branch" do
+ AST::Nop.expects(:new)
+ @parser.parse("if true { }")
+ end
+
+ it "should create a nop node for empty else branch" do
+ AST::Nop.expects(:new)
+ @parser.parse("if true { notice('test') } else { }")
+ end
+
+ end
+
+ end
diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb
index ec8ab6d7d..fa76c4ff2 100755
--- a/spec/unit/parser/scope.rb
+++ b/spec/unit/parser/scope.rb
@@ -34,4 +34,54 @@ describe Puppet::Parser::Scope do
end
end
+
+ describe Puppet::Parser::Scope, "when calling number?" do
+
+ it "should return nil if called with anything not a number" do
+ Puppet::Parser::Scope.number?([2]).should be_nil
+ end
+
+ it "should return a Fixnum for a Fixnum" do
+ Puppet::Parser::Scope.number?(2).should be_an_instance_of(Fixnum)
+ end
+
+ it "should return a Float for a Float" do
+ Puppet::Parser::Scope.number?(2.34).should be_an_instance_of(Float)
+ end
+
+ it "should return 234 for '234'" do
+ Puppet::Parser::Scope.number?("234").should == 234
+ end
+
+ it "should return nil for 'not a number'" do
+ Puppet::Parser::Scope.number?("not a number").should be_nil
+ end
+
+ it "should return 23.4 for '23.4'" do
+ Puppet::Parser::Scope.number?("23.4").should == 23.4
+ end
+
+ it "should return 23.4e13 for '23.4e13'" do
+ Puppet::Parser::Scope.number?("23.4e13").should == 23.4e13
+ end
+
+ it "should understand negative numbers" do
+ Puppet::Parser::Scope.number?("-234").should == -234
+ end
+
+ it "should know how to convert exponential float numbers ala '23e13'" do
+ Puppet::Parser::Scope.number?("23e13").should == 23e13
+ end
+
+ it "should understand hexadecimal numbers" do
+ Puppet::Parser::Scope.number?("0x234").should == 0x234
+ end
+
+ it "should understand octal numbers" do
+ Puppet::Parser::Scope.number?("0755").should == 0755
+ end
+
+
+ end
+
end
diff --git a/spec/unit/property/list.rb b/spec/unit/property/list.rb
new file mode 100644
index 000000000..9c832c0cd
--- /dev/null
+++ b/spec/unit/property/list.rb
@@ -0,0 +1,147 @@
+#!/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/property/list'
+
+list_class = Puppet::Property::List
+
+describe list_class do
+
+ it "should be a subclass of Property" do
+ list_class.superclass.must == Puppet::Property
+ end
+
+ describe "as an instance" do
+ before do
+ # Wow that's a messy interface to the resource.
+ list_class.initvars
+ @resource = stub 'resource', :[]= => nil, :property => nil
+ @property = list_class.new(:resource => @resource)
+ end
+
+ it "should have a , as default delimiter" do
+ @property.delimiter.should == ","
+ end
+
+ it "should have a :membership as default membership" do
+ @property.membership.should == :membership
+ end
+
+ it "should return the same value passed into should_to_s" do
+ @property.should_to_s("foo") == "foo"
+ end
+
+ it "should return the passed in array values joined with the delimiter from is_to_s" do
+ @property.is_to_s(["foo","bar"]).should == "foo,bar"
+ end
+
+ describe "when adding should to current" do
+ it "should add the arrays when current is an array" do
+ @property.add_should_with_current(["foo"], ["bar"]).should == ["foo", "bar"]
+ end
+
+ it "should return should if current is not a array" do
+ @property.add_should_with_current(["foo"], :absent).should == ["foo"]
+ end
+
+ it "should return only the uniq elements" do
+ @property.add_should_with_current(["foo", "bar"], ["foo", "baz"]).should == ["foo", "bar", "baz"]
+ end
+ end
+
+ describe "when calling inclusive?" do
+ it "should use the membership method to look up on the @resource" do
+ @property.expects(:membership).returns(:membership)
+ @resource.expects(:[]).with(:membership)
+ @property.inclusive?
+ end
+
+ it "should return true when @resource[membership] == inclusive" do
+ @property.stubs(:membership).returns(:membership)
+ @resource.stubs(:[]).with(:membership).returns(:inclusive)
+ @property.inclusive?.must == true
+ end
+
+ it "should return false when @resource[membership] != inclusive" do
+ @property.stubs(:membership).returns(:membership)
+ @resource.stubs(:[]).with(:membership).returns(:minimum)
+ @property.inclusive?.must == false
+ end
+ end
+
+ describe "when calling should" do
+ it "should return nil if @should is nil" do
+ @property.should.must == nil
+ end
+
+ it "should return the sorted values of @should as a string if inclusive" do
+ @property.should = ["foo", "bar"]
+ @property.expects(:inclusive?).returns(true)
+ @property.should.must == "bar,foo"
+ end
+
+ it "should return the uniq sorted values of @should + retrieve as a string if !inclusive" do
+ @property.should = ["foo", "bar"]
+ @property.expects(:inclusive?).returns(false)
+ @property.expects(:retrieve).returns(["foo","baz"])
+ @property.should.must == "bar,baz,foo"
+ end
+ end
+
+ describe "when calling retrieve" do
+ before do
+ @provider = mock("provider")
+ @property.stubs(:provider).returns(@provider)
+ end
+
+ it "should send 'name' to the provider" do
+ @provider.expects(:send).with(:group)
+ @property.expects(:name).returns(:group)
+ @property.retrieve
+ end
+
+ it "should return an array with the provider returned info" do
+ @provider.stubs(:send).with(:group).returns("foo,bar,baz")
+ @property.stubs(:name).returns(:group)
+ @property.retrieve == ["foo", "bar", "baz"]
+ end
+
+ it "should return :absent when the provider returns :absent" do
+ @provider.stubs(:send).with(:group).returns(:absent)
+ @property.stubs(:name).returns(:group)
+ @property.retrieve == :absent
+ end
+ end
+
+ describe "when calling insync?" do
+ it "should return true unless @should is defined and not nil" do
+ @property.insync?("foo") == true
+ end
+
+ it "should return true unless the passed in values is not nil" do
+ @property.should = "foo"
+ @property.insync?(nil) == true
+ end
+
+ it "should call prepare_is_for_comparison with value passed in and should" do
+ @property.should = "foo"
+ @property.expects(:prepare_is_for_comparison).with("bar")
+ @property.expects(:should)
+ @property.insync?("bar")
+ end
+
+ it "should return true if prepared value == should value" do
+ @property.should = "bar,foo"
+ @property.expects(:inclusive?).returns(true)
+ @property.insync?(["bar","foo"]).must == true
+ end
+
+ it "should return false if prepared value != should value" do
+ @property.should = "bar,baz,foo"
+ @property.expects(:inclusive?).returns(true)
+ @property.insync?(["bar","foo"]).must == false
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/package/apt.rb b/spec/unit/provider/package/apt.rb
new file mode 100755
index 000000000..0ec1cd9ed
--- /dev/null
+++ b/spec/unit/provider/package/apt.rb
@@ -0,0 +1,138 @@
+#!/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") }
+
+provider = Puppet::Type.type(:package).provider(:apt)
+
+describe provider do
+ before do
+ @resource = stub 'resource', :[] => "asdf"
+ @provider = provider.new(@resource)
+
+ @fakeresult = "install ok installed asdf 1.0\n"
+ end
+
+ it "should be versionable" do
+ provider.should be_versionable
+ end
+
+ it "should use :install to update" do
+ @provider.expects(:install)
+ @provider.update
+ end
+
+ it "should use 'apt-get remove' to uninstall" do
+ @provider.expects(:aptget).with("-y", "-q", :remove, "asdf")
+
+ @provider.uninstall
+ end
+
+ it "should use 'apt-get purge' and 'dpkg purge' to purge" do
+ @provider.expects(:aptget).with("-y", "-q", :remove, "--purge", "asdf")
+ @provider.expects(:dpkg).with("--purge", "asdf")
+
+ @provider.purge
+ end
+
+ it "should use 'apt-cache policy' to determine the latest version of a package" do
+ @provider.expects(:aptcache).with(:policy, "asdf").returns "asdf:
+Installed: 1:1.0
+Candidate: 1:1.1
+Version table:
+ 1:1.0
+ 650 http://ftp.osuosl.org testing/main Packages
+*** 1:1.1
+ 100 /var/lib/dpkg/status"
+
+ @provider.latest.should == "1:1.1"
+ end
+
+ it "should print and error and return nil if no policy is found" do
+ @provider.expects(:aptcache).with(:policy, "asdf").returns "asdf:"
+
+ @provider.expects(:err)
+ @provider.latest.should be_nil
+ end
+
+ it "should be able to preseed" do
+ @provider.should respond_to(:run_preseed)
+ end
+
+ it "should preseed with the provided responsefile when preseeding is called for" do
+ @resource.expects(:[]).with(:responsefile).returns "/my/file"
+ FileTest.expects(:exist?).with("/my/file").returns true
+
+ @provider.expects(:info)
+ @provider.expects(:preseed).with("/my/file")
+
+ @provider.run_preseed
+ end
+
+ it "should not preseed if no responsefile is provided" do
+ @resource.expects(:[]).with(:responsefile).returns nil
+
+ @provider.expects(:info)
+ @provider.expects(:preseed).never
+
+ @provider.run_preseed
+ end
+
+ it "should fail if a cdrom is listed in the sources list and :allowcdrom is not specified"
+
+ describe "when installing" do
+ it "should preseed if a responsefile is provided" do
+ @resource.expects(:[]).with(:responsefile).returns "/my/file"
+ @provider.expects(:run_preseed)
+
+ @provider.stubs(:aptget)
+ @provider.install
+ end
+
+ it "should check for a cdrom" do
+ @provider.expects(:checkforcdrom)
+
+ @provider.stubs(:aptget)
+ @provider.install
+ end
+
+ it "should use 'apt-get install' with the package name if no version is asked for" do
+ @resource.expects(:[]).with(:ensure).returns :installed
+ @provider.expects(:aptget).with { |*command| command[-1] == "asdf" and command[-2] == :install }
+
+ @provider.install
+ end
+
+ it "should specify the package version if one is asked for" do
+ @resource.expects(:[]).with(:ensure).returns "1.0"
+ @provider.expects(:aptget).with { |*command| command[-1] == "asdf=1.0" }
+
+ @provider.install
+ end
+
+ it "should do a quiet install" do
+ @provider.expects(:aptget).with { |*command| command.include?("-q") }
+
+ @provider.install
+ end
+
+ it "should default to 'yes' for all questions" do
+ @provider.expects(:aptget).with { |*command| command.include?("-y") }
+
+ @provider.install
+ end
+
+ it "should keep config files if asked" do
+ @resource.expects(:[]).with(:configfiles).returns :keep
+ @provider.expects(:aptget).with { |*command| command.include?("DPkg::Options::=--force-confold") }
+
+ @provider.install
+ end
+
+ it "should replace config files if asked" do
+ @resource.expects(:[]).with(:configfiles).returns :replace
+ @provider.expects(:aptget).with { |*command| command.include?("DPkg::Options::=--force-confnew") }
+
+ @provider.install
+ end
+ end
+end
diff --git a/spec/unit/provider/package/dpkg.rb b/spec/unit/provider/package/dpkg.rb
new file mode 100755
index 000000000..08aaca875
--- /dev/null
+++ b/spec/unit/provider/package/dpkg.rb
@@ -0,0 +1,163 @@
+#!/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") }
+
+provider = Puppet::Type.type(:package).provider(:dpkg)
+
+describe provider do
+ before do
+ @resource = stub 'resource', :[] => "asdf"
+ @provider = provider.new(@resource)
+
+ @fakeresult = "install ok installed asdf 1.0\n"
+ end
+
+ it "should have documentation" do
+ provider.doc.should be_instance_of(String)
+ end
+
+ describe "when listing all instances" do
+ before do
+ provider.stubs(:command).with(:dpkgquery).returns "myquery"
+ end
+
+ it "should use dpkg-query" do
+ provider.expects(:command).with(:dpkgquery).returns "myquery"
+ provider.expects(:execpipe).with("myquery -W --showformat '${Status} ${Package} ${Version}\\n'").returns @fakeresult
+
+ provider.instances
+ end
+
+ it "should create and return an instance with each parsed line from dpkg-query" do
+ pipe = mock 'pipe'
+ pipe.expects(:each).yields @fakeresult
+ provider.expects(:execpipe).yields pipe
+
+ asdf = mock 'pkg1'
+ provider.expects(:new).with(:ensure => "1.0", :error => "ok", :desired => "install", :name => "asdf", :status => "installed", :provider => :dpkg).returns asdf
+
+ provider.instances.should == [asdf]
+ end
+
+ it "should warn on and ignore any lines it does not understand" do
+ pipe = mock 'pipe'
+ pipe.expects(:each).yields "foobar"
+ provider.expects(:execpipe).yields pipe
+
+ Puppet.expects(:warning)
+ provider.expects(:new).never
+
+ provider.instances.should == []
+ end
+ end
+
+ describe "when querying the current state" do
+ it "should use dpkg-query" do
+ @provider.expects(:dpkgquery).with("-W", "--showformat",'${Status} ${Package} ${Version}\\n', "asdf").returns @fakeresult
+
+ @provider.query
+ end
+
+ it "should consider the package purged if dpkg-query fails" do
+ @provider.expects(:dpkgquery).raises Puppet::ExecutionFailure.new("eh")
+
+ @provider.query[:ensure].should == :purged
+ end
+
+ it "should return a hash of the found status with the desired state, error state, status, name, and 'ensure'" do
+ @provider.expects(:dpkgquery).returns @fakeresult
+
+ @provider.query.should == {:ensure => "1.0", :error => "ok", :desired => "install", :name => "asdf", :status => "installed", :provider => :dpkg}
+ end
+
+ it "should consider the package absent if the dpkg-query result cannot be interpreted" do
+ @provider.expects(:dpkgquery).returns "somebaddata"
+
+ @provider.query[:ensure].should == :absent
+ end
+
+ it "should fail if an error is discovered" do
+ @provider.expects(:dpkgquery).returns @fakeresult.sub("ok", "error")
+
+ lambda { @provider.query }.should raise_error(Puppet::Error)
+ end
+
+ it "should consider the package purged if it is marked 'not-installed'" do
+ @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "not-installed")
+
+ @provider.query[:ensure].should == :purged
+ end
+
+ it "should consider the package absent if its status is neither 'installed' nor 'not-installed'" do
+ @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "foo")
+
+ @provider.query[:ensure].should == :absent
+ end
+ end
+
+ it "should be able to install" do
+ @provider.should respond_to(:install)
+ end
+
+ describe "when installing" do
+ before do
+ @resource.stubs(:[]).with(:source).returns "mypkg"
+ end
+
+ it "should fail to install if no source is specified in the resource" do
+ @resource.expects(:[]).with(:source).returns nil
+
+ lambda { @provider.install }.should raise_error(ArgumentError)
+ end
+
+ it "should use 'dpkg -i' to install the package" do
+ @resource.expects(:[]).with(:source).returns "mypackagefile"
+ @provider.expects(:dpkg).with { |*command| command[-1] == "mypackagefile" and command[-2] == "-i" }
+
+ @provider.install
+ end
+
+ it "should keep old config files if told to do so" do
+ @resource.expects(:[]).with(:configfiles).returns :keep
+ @provider.expects(:dpkg).with { |*command| command[0] == "--force-confold" }
+
+ @provider.install
+ end
+
+ it "should replace old config files if told to do so" do
+ @resource.expects(:[]).with(:configfiles).returns :replace
+ @provider.expects(:dpkg).with { |*command| command[0] == "--force-confnew" }
+
+ @provider.install
+ end
+ end
+
+ it "should use :install to update" do
+ @provider.expects(:install)
+ @provider.update
+ end
+
+ describe "when determining latest available version" do
+ it "should return the version found by dpkg-deb" do
+ @resource.expects(:[]).with(:source).returns "myfile"
+ @provider.expects(:dpkg_deb).with { |*command| command[-1] == "myfile" }.returns "asdf\t1.0"
+ @provider.latest.should == "1.0"
+ end
+
+ it "should warn if the package file contains a different package" do
+ @provider.expects(:dpkg_deb).returns("foo\tversion")
+ @provider.expects(:warning)
+ @provider.latest
+ end
+ end
+
+ it "should use 'dpkg -r' to uninstall" do
+ @provider.expects(:dpkg).with("-r", "asdf")
+ @provider.uninstall
+ end
+
+ it "should use 'dpkg --purge' to purge" do
+ @provider.expects(:dpkg).with("--purge", "asdf")
+ @provider.purge
+ end
+end
diff --git a/spec/unit/provider/selboolean.rb b/spec/unit/provider/selboolean.rb
new file mode 100755
index 000000000..4006df151
--- /dev/null
+++ b/spec/unit/provider/selboolean.rb
@@ -0,0 +1,37 @@
+#!/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") }
+
+provider_class = Puppet::Type.type(:selboolean).provider(:getsetsebool)
+
+describe provider_class do
+ before :each do
+ @resource = stub("resource", :name => "foo")
+ @resource.stubs(:[]).returns "foo"
+ @provider = provider_class.new(@resource)
+ end
+
+ it "should return :on when getsebool returns on" do
+ @provider.expects(:getsebool).with("foo").returns "foo --> on\n"
+ @provider.value.should == :on
+ end
+
+ it "should return :off when getsebool returns on" do
+ @provider.expects(:getsebool).with("foo").returns "foo --> off\n"
+ @provider.value.should == :off
+ end
+
+ it "should call execpipe when updating boolean setting" do
+ @provider.expects(:command).with(:setsebool).returns "/usr/sbin/setsebool"
+ @provider.expects(:execpipe).with("/usr/sbin/setsebool foo off")
+ @provider.value = :off
+ end
+
+ it "should call execpipe with -P when updating persistent boolean setting" do
+ @resource.stubs(:[]).with(:persistent).returns :true
+ @provider.expects(:command).with(:setsebool).returns "/usr/sbin/setsebool"
+ @provider.expects(:execpipe).with("/usr/sbin/setsebool -P foo off")
+ @provider.value = :off
+ end
+
+end
diff --git a/spec/unit/provider/selmodule-example.pp b/spec/unit/provider/selmodule-example.pp
new file mode 100644
index 000000000..28166ca40
--- /dev/null
+++ b/spec/unit/provider/selmodule-example.pp
Binary files differ
diff --git a/spec/unit/provider/selmodule.rb b/spec/unit/provider/selmodule.rb
new file mode 100755
index 000000000..e92441d23
--- /dev/null
+++ b/spec/unit/provider/selmodule.rb
@@ -0,0 +1,66 @@
+#!/usr/bin/env ruby
+
+# Note: This unit test depends on having a sample SELinux policy file
+# in the same directory as this test called selmodule-example.pp
+# with version 1.5.0. The provided selmodule-example.pp is the first
+# 256 bytes taken from /usr/share/selinux/targeted/nagios.pp on Fedora 9
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+provider_class = Puppet::Type.type(:selmodule).provider(:semodule)
+
+describe provider_class do
+ before :each do
+ @resource = stub("resource", :name => "foo")
+ @resource.stubs(:[]).returns "foo"
+ @provider = provider_class.new(@resource)
+ end
+
+ describe "exists? method" do
+ it "should find a module if it is already loaded" do
+ @provider.expects(:command).with(:semodule).returns "/usr/sbin/semodule"
+ @provider.expects(:execpipe).with("/usr/sbin/semodule --list").yields ["bar\t1.2.3\n", "foo\t4.4.4\n", "bang\t1.0.0\n"]
+ @provider.exists?.should == :true
+ end
+
+ it "should return nil if not loaded" do
+ @provider.expects(:command).with(:semodule).returns "/usr/sbin/semodule"
+ @provider.expects(:execpipe).with("/usr/sbin/semodule --list").yields ["bar\t1.2.3\n", "bang\t1.0.0\n"]
+ @provider.exists?.should be_nil
+ end
+
+ it "should return nil if no modules are loaded" do
+ @provider.expects(:command).with(:semodule).returns "/usr/sbin/semodule"
+ @provider.expects(:execpipe).with("/usr/sbin/semodule --list").yields []
+ @provider.exists?.should be_nil
+ end
+ end
+
+ describe "selmodversion_file" do
+ it "should return 1.5.0 for the example policy file" do
+ @provider.expects(:selmod_name_to_filename).returns "#{File.dirname(__FILE__)}/selmodule-example.pp"
+ @provider.selmodversion_file.should == "1.5.0"
+ end
+ end
+
+ describe "syncversion" do
+ it "should return :true if loaded and file modules are in sync" do
+ @provider.expects(:selmodversion_loaded).returns "1.5.0"
+ @provider.expects(:selmodversion_file).returns "1.5.0"
+ @provider.syncversion.should == :true
+ end
+
+ it "should return :false if loaded and file modules are not in sync" do
+ @provider.expects(:selmodversion_loaded).returns "1.4.0"
+ @provider.expects(:selmodversion_file).returns "1.5.0"
+ @provider.syncversion.should == :false
+ end
+
+ it "should return before checking file version if no loaded policy" do
+ @provider.expects(:selmodversion_loaded).returns nil
+ @provider.syncversion.should == :false
+ end
+
+ end
+
+end
diff --git a/spec/unit/provider/user/user_role_add.rb b/spec/unit/provider/user/user_role_add.rb
new file mode 100644
index 000000000..e9bd9a68f
--- /dev/null
+++ b/spec/unit/provider/user/user_role_add.rb
@@ -0,0 +1,131 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:user).provider(:user_role_add)
+
+describe provider_class do
+ before do
+ @resource = stub("resource", :name => "myuser", :managehome? => nil)
+ @resource.stubs(:should).returns "fakeval"
+ @resource.stubs(:[]).returns "fakeval"
+ @resource.stubs(:allowdupe?).returns false
+ @provider = provider_class.new(@resource)
+ end
+
+ describe "when calling command" do
+ before do
+ klass = stub("provider")
+ klass.stubs(:command).with(:foo).returns("userfoo")
+ klass.stubs(:command).with(:role_foo).returns("rolefoo")
+ @provider.stubs(:class).returns(klass)
+ end
+
+ it "should use the command if not a role and ensure!=role" do
+ @provider.stubs(:is_role?).returns(false)
+ @provider.stubs(:exists?).returns(false)
+ @resource.stubs(:[]).with(:ensure).returns(:present)
+ @provider.command(:foo).should == "userfoo"
+ end
+
+ it "should use the role command when a role" do
+ @provider.stubs(:is_role?).returns(true)
+ @provider.command(:foo).should == "rolefoo"
+ end
+
+ it "should use the role command when !exists and ensure=role" do
+ @provider.stubs(:is_role?).returns(false)
+ @provider.stubs(:exists?).returns(false)
+ @resource.stubs(:[]).with(:ensure).returns(:role)
+ @provider.command(:foo).should == "rolefoo"
+ end
+ end
+
+ describe "when calling transition" do
+ it "should return foomod setting the type to bar" do
+ @provider.expects(:command).with(:modify).returns("foomod")
+ @provider.transition("bar").should == ["foomod", "-K", "type=bar", "fakeval"]
+ end
+ end
+
+ describe "when calling create" do
+ it "should use the add command when the user is not a role" do
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:addcmd).returns("useradd")
+ @provider.expects(:run)
+ @provider.create
+ end
+
+ it "should use transition(normal) when the user is a role" do
+ @provider.stubs(:is_role?).returns(true)
+ @provider.expects(:transition).with("normal")
+ @provider.expects(:run)
+ @provider.create
+ end
+ end
+
+ describe "when calling destroy" do
+ it "should use the delete command if the user exists and is not a role" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:deletecmd)
+ @provider.expects(:run)
+ @provider.destroy
+ end
+
+ it "should use the delete command if the user is a role" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(true)
+ @provider.expects(:deletecmd)
+ @provider.expects(:run)
+ @provider.destroy
+ end
+ end
+
+ describe "when calling create_role" do
+ it "should use the transition(role) if the user exists" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:transition).with("role")
+ @provider.expects(:run)
+ @provider.create_role
+ end
+
+ it "should use the add command when role doesn't exists" do
+ @provider.stubs(:exists?).returns(false)
+ @provider.expects(:addcmd)
+ @provider.expects(:run)
+ @provider.create_role
+ end
+ end
+
+ describe "when allow duplicate is enabled" do
+ before do
+ @resource.expects(:allowdupe?).returns true
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:execute).with { |args| args.include?("-o") }
+ end
+
+ it "should add -o when the user is being created" do
+ @provider.create
+ end
+
+ it "should add -o when the uid is being modified" do
+ @provider.uid = 150
+ end
+ end
+
+ describe "when getting roles" do
+ it "should get the user_attributes" do
+ @provider.expects(:user_attributes)
+ @provider.roles
+ end
+
+ it "should get the :roles attribute" do
+ attributes = mock("attributes")
+ attributes.expects(:[]).with(:roles)
+ @provider.stubs(:user_attributes).returns(attributes)
+ @provider.roles
+ end
+ end
+end
diff --git a/spec/unit/type.rb b/spec/unit/type.rb
index 9815ed32d..5e6cf3357 100755
--- a/spec/unit/type.rb
+++ b/spec/unit/type.rb
@@ -2,28 +2,63 @@
require File.dirname(__FILE__) + '/../spec_helper'
-describe Puppet::Type, " when in a configuration" do
- before do
- @catalog = Puppet::Node::Catalog.new
- @container = Puppet::Type.type(:component).create(:name => "container")
- @one = Puppet::Type.type(:file).create(:path => "/file/one")
- @two = Puppet::Type.type(:file).create(:path => "/file/two")
- @catalog.add_resource @container
- @catalog.add_resource @one
- @catalog.add_resource @two
- @catalog.add_edge @container, @one
- @catalog.add_edge @container, @two
- end
+describe Puppet::Type do
+ describe "when retrieving current properties" do
+ # Use 'mount' as an example, because it doesn't override 'retrieve'
+ before do
+ @resource = Puppet::Type.type(:mount).create(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present)
+ @properties = {}
+ end
- it "should have no parent if there is no in edge" do
- @container.parent.should be_nil
- end
+ after { Puppet::Type.type(:mount).clear }
+
+ it "should return a hash containing values for all set properties" do
+ values = @resource.retrieve
+ [@resource.property(:fstype), @resource.property(:pass)].each { |property| values.should be_include(property) }
+ end
+
+ it "should not call retrieve on non-ensure properties if the resource is absent" do
+ @resource.property(:ensure).expects(:retrieve).returns :absent
+ @resource.property(:fstype).expects(:retrieve).never
+ @resource.retrieve[@resource.property(:fstype)]
+ end
+
+ it "should set all values to :absent if the resource is absent" do
+ @resource.property(:ensure).expects(:retrieve).returns :absent
+ @resource.retrieve[@resource.property(:fstype)].should == :absent
+ end
- it "should set its parent to its in edge" do
- @one.parent.ref.should == @container.ref
+ it "should include the result of retrieving each property's current value if the resource is present" do
+ @resource.property(:ensure).expects(:retrieve).returns :present
+ @resource.property(:fstype).expects(:retrieve).returns 15
+ @resource.retrieve[@resource.property(:fstype)].should == 15
+ end
end
- after do
- @catalog.clear(true)
+
+ describe "when in a catalog" do
+ before do
+ @catalog = Puppet::Node::Catalog.new
+ @container = Puppet::Type.type(:component).create(:name => "container")
+ @one = Puppet::Type.type(:file).create(:path => "/file/one")
+ @two = Puppet::Type.type(:file).create(:path => "/file/two")
+ @catalog.add_resource @container
+ @catalog.add_resource @one
+ @catalog.add_resource @two
+ @catalog.add_edge @container, @one
+ @catalog.add_edge @container, @two
+ end
+
+ it "should have no parent if there is no in edge" do
+ @container.parent.should be_nil
+ end
+
+ it "should set its parent to its in edge" do
+ @one.parent.ref.should == @container.ref
+ end
+
+ after do
+ @catalog.clear(true)
+ end
end
end
diff --git a/spec/unit/type/file.rb b/spec/unit/type/file.rb
index fd790d678..552d284a7 100755
--- a/spec/unit/type/file.rb
+++ b/spec/unit/type/file.rb
@@ -41,6 +41,14 @@ describe Puppet::Type.type(:file) do
lambda { @file.retrieve }.should raise_error(Puppet::Error)
end
+ it "should always have a checksum type of md5" do
+ File.open(@path, "w") do |f| f.puts "foo" end
+ @file[:checksum] = :mtime
+ @file.property(:checksum).checktype.should == :md5
+ @file.property(:checksum).retrieve.should == "{md5}d3b07384d113edec49eaa6238ad5ff00"
+ @file.property(:checksum).getsum(:mtime).should == "{md5}d3b07384d113edec49eaa6238ad5ff00"
+ end
+
end
describe "when retrieving remote files" do
diff --git a/spec/unit/type/file/group.rb b/spec/unit/type/file/group.rb
new file mode 100755
index 000000000..856b05b0d
--- /dev/null
+++ b/spec/unit/type/file/group.rb
@@ -0,0 +1,118 @@
+#!/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") }
+
+property = Puppet::Type.type(:file).attrclass(:group)
+
+describe property do
+ before do
+ @resource = stub 'resource', :line => "foo", :file => "bar"
+ @resource.stubs(:[]).returns "foo"
+ @resource.stubs(:[]).with(:path).returns "/my/file"
+ @group = property.new :resource => @resource
+ end
+
+ it "should have a method for testing whether a group is valid" do
+ @group.must respond_to(:validgroup?)
+ end
+
+ it "should return the found gid if a group is valid" do
+ @group.expects(:gid).with("foo").returns 500
+ @group.validgroup?("foo").should == 500
+ end
+
+ it "should return false if a group is not valid" do
+ @group.expects(:gid).with("foo").returns nil
+ @group.validgroup?("foo").should be_false
+ end
+
+ describe "when retrieving the current value" do
+ it "should return :absent if the file cannot stat" do
+ @resource.expects(:stat).returns nil
+
+ @group.retrieve.should == :absent
+ end
+
+ it "should get the gid from the stat instance from the file" do
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ stat.expects(:gid).returns 500
+
+ @group.retrieve.should == 500
+ end
+
+ it "should warn and return :silly if the found value is higher than the maximum uid value" do
+ Puppet.settings.expects(:value).with(:maximum_uid).returns 500
+
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ stat.expects(:gid).returns 1000
+
+ @group.expects(:warning)
+ @group.retrieve.should == :silly
+ end
+ end
+
+ describe "when determining if the file is in sync" do
+ it "should directly compare the group values if the desired group is an integer" do
+ @group.should = [10]
+ @group.must be_insync(10)
+ end
+
+ it "should treat numeric strings as integers" do
+ @group.should = ["10"]
+ @group.must be_insync(10)
+ end
+
+ it "should convert the group name to an integer if the desired group is a string" do
+ @group.expects(:gid).with("foo").returns 10
+ @group.should = %w{foo}
+
+ @group.must be_insync(10)
+ end
+
+ it "should fail if it cannot convert a group name to an integer" do
+ @group.expects(:gid).with("foo").returns nil
+ @group.should = %w{foo}
+
+ lambda { @group.insync?(10) }.should raise_error(Puppet::Error)
+ end
+
+ it "should return false if the groups are not equal" do
+ @group.should = [10]
+ @group.should_not be_insync(20)
+ end
+ end
+
+ describe "when changing the group" do
+ before do
+ @group.should = %w{one}
+ @group.stubs(:gid).returns 500
+ end
+
+ it "should chown the file if :links is set to :follow" do
+ @resource.expects(:[]).with(:links).returns :follow
+ File.expects(:chown)
+
+ @group.sync
+ end
+
+ it "should lchown the file if :links is set to :manage" do
+ @resource.expects(:[]).with(:links).returns :manage
+ File.expects(:lchown)
+
+ @group.sync
+ end
+
+ it "should use the first valid group in its 'should' list" do
+ @group.should = %w{one two three}
+ @group.expects(:validgroup?).with("one").returns nil
+ @group.expects(:validgroup?).with("two").returns 500
+ @group.expects(:validgroup?).with("three").never
+
+ File.expects(:chown).with(nil, 500, "/my/file")
+
+ @group.sync
+ end
+ end
+end
diff --git a/spec/unit/type/file/selinux.rb b/spec/unit/type/file/selinux.rb
new file mode 100644
index 000000000..5e2c3539c
--- /dev/null
+++ b/spec/unit/type/file/selinux.rb
@@ -0,0 +1,82 @@
+#!/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") }
+
+
+[:seluser, :selrole, :seltype, :selrange].each do |param|
+property = Puppet::Type.type(:file).attrclass(param)
+ describe property do
+ before do
+ @resource = mock 'resource'
+ @resource.stubs(:[]).with(:path).returns "/my/file"
+ @sel = property.new :resource => @resource
+ end
+
+ it "retrieve on #{param} should return :absent if the file isn't statable" do
+ @resource.expects(:stat).returns nil
+ @sel.retrieve.should == :absent
+ end
+
+ it "should retrieve nil for #{param} if there is no SELinux support" do
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ @sel.expects(:get_selinux_current_context).with("/my/file").returns nil
+ @sel.retrieve.should be_nil
+ end
+
+ it "should retrieve #{param} if a SELinux context is found with a range" do
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ @sel.expects(:get_selinux_current_context).with("/my/file").returns "user_u:role_r:type_t:s0"
+ expectedresult = case param
+ when :seluser then "user_u"
+ when :selrole then "role_r"
+ when :seltype then "type_t"
+ when :selrange then "s0"
+ end
+ @sel.retrieve.should == expectedresult
+ end
+
+ it "should retrieve #{param} if a SELinux context is found without a range" do
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ @sel.expects(:get_selinux_current_context).with("/my/file").returns "user_u:role_r:type_t"
+ expectedresult = case param
+ when :seluser then "user_u"
+ when :selrole then "role_r"
+ when :seltype then "type_t"
+ when :selrange then nil
+ end
+ @sel.retrieve.should == expectedresult
+ end
+
+ it "should handle no default gracefully" do
+ @sel.expects(:get_selinux_default_context).with("/my/file").returns nil
+ @sel.default.must be_nil
+ end
+
+ it "should be able to detect matchpathcon defaults" do
+ @sel.expects(:get_selinux_default_context).with("/my/file").returns "user_u:role_r:type_t:s0"
+ expectedresult = case param
+ when :seluser then "user_u"
+ when :selrole then "role_r"
+ when :seltype then "type_t"
+ when :selrange then "s0"
+ end
+ @sel.default.must == expectedresult
+ end
+
+ it "should be able to set a new context" do
+ stat = stub 'stat', :ftype => "foo"
+ @resource.expects(:stat).returns stat
+ @sel.should = %w{newone}
+ @sel.expects(:set_selinux_context).with("/my/file", ["newone"], param)
+ @sel.sync
+ end
+
+ after do
+ Puppet::Type.type(:file).clear
+ end
+ end
+end
+
diff --git a/spec/unit/type/selboolean.rb b/spec/unit/type/selboolean.rb
new file mode 100755
index 000000000..14b3b7290
--- /dev/null
+++ b/spec/unit/type/selboolean.rb
@@ -0,0 +1,47 @@
+#!/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(:selboolean), "when validating attributes" do
+ [:name, :persistent].each do |param|
+ it "should have a #{param} parameter" do
+ Puppet::Type.type(:selboolean).attrtype(param).should == :param
+ end
+ end
+
+ it "should have a value property" do
+ Puppet::Type.type(:selboolean).attrtype(:value).should == :property
+ end
+end
+
+describe Puppet::Type.type(:selboolean), "when validating values" do
+ before do
+ @class = Puppet::Type.type(:selboolean)
+
+ @provider_class = stub 'provider_class', :name => "fake", :suitable? => true, :supports_parameter? => true
+ @class.stubs(:defaultprovider).returns(@provider_class)
+ @class.stubs(:provider).returns(@provider_class)
+
+ @provider = stub 'provider', :class => @provider_class, :clear => nil
+ @provider_class.stubs(:new).returns(@provider)
+ end
+
+ it "should support :on as a value to :value" do
+ Puppet::Type.type(:selboolean).create(:name => "yay", :value => :on)
+ end
+
+ it "should support :off as a value to :value" do
+ Puppet::Type.type(:selboolean).create(:name => "yay", :value => :off)
+ end
+
+ it "should support :true as a value to :persistent" do
+ Puppet::Type.type(:selboolean).create(:name => "yay", :value => :on, :persistent => :true)
+ end
+
+ it "should support :false as a value to :persistent" do
+ Puppet::Type.type(:selboolean).create(:name => "yay", :value => :on, :persistent => :false)
+ end
+
+ after { Puppet::Type.type(:selboolean).clear }
+end
+
diff --git a/spec/unit/type/selmodule.rb b/spec/unit/type/selmodule.rb
new file mode 100755
index 000000000..f14bea9d3
--- /dev/null
+++ b/spec/unit/type/selmodule.rb
@@ -0,0 +1,18 @@
+#!/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(:selmodule), "when validating attributes" do
+ [:name, :selmoduledir, :selmodulepath].each do |param|
+ it "should have a #{param} parameter" do
+ Puppet::Type.type(:selmodule).attrtype(param).should == :param
+ end
+ end
+
+ [:ensure, :syncversion].each do |param|
+ it "should have a #{param} property" do
+ Puppet::Type.type(:selmodule).attrtype(param).should == :property
+ end
+ end
+end
+
diff --git a/spec/unit/type/user.rb b/spec/unit/type/user.rb
index d16d752f9..51c6dd801 100755
--- a/spec/unit/type/user.rb
+++ b/spec/unit/type/user.rb
@@ -2,55 +2,186 @@
require File.dirname(__FILE__) + '/../../spec_helper'
-module UserTestFunctions
- def mkuser(name)
- user = nil;
- lambda {
- user = Puppet::Type.type(:user).create(
- :name => name,
- :comment => "Puppet Testing User",
- :gid => Puppet::Util::SUIDManager.gid,
- :shell => "/bin/sh",
- :home => "/home/%s" % name
- ) }.should_not raise_error
- user.should_not be_nil
- user
- end
-
- def test_provider_class(klass)
- klass.should_not be_nil
- klass.should be_an_instance_of(Class)
- superclasses = []
- while klass = klass.superclass
- superclasses << klass
- end
- superclasses.should include(Puppet::Provider)
- end
-end
+user = Puppet::Type.type(:user)
-describe Puppet::Type.type(:user) do
+describe user do
+ before do
+ @provider = stub 'provider'
+ @resource = stub 'resource', :resource => nil, :provider => @provider, :line => nil, :file => nil
+ end
- include UserTestFunctions
+ after { user.clear }
it "should have a default provider inheriting from Puppet::Provider" do
- test_provider_class Puppet::Type.type(:user).defaultprovider
+ user.defaultprovider.ancestors.should be_include(Puppet::Provider)
end
it "should be able to create a instance" do
- mkuser "123testuser1"
+ user.create(:name => "foo").should_not be_nil
end
-end
-describe Puppet::Type.type(:user), "instances" do
+ it "should have an allows_duplicates feature" do
+ user.provider_feature(:allows_duplicates).should_not be_nil
+ end
- include UserTestFunctions
+ it "should have an manages_homedir feature" do
+ user.provider_feature(:manages_homedir).should_not be_nil
+ end
- it "should have a valid provider" do
- user = mkuser "123testuser2"
- user.provider.should_not be_nil
- test_provider_class user.provider.class
+ it "should have an manages_passwords feature" do
+ user.provider_feature(:manages_passwords).should_not be_nil
end
-end
+ describe "instances" do
+ it "should have a valid provider" do
+ user.create(:name => "foo").provider.class.ancestors.should be_include(Puppet::Provider)
+ end
+ end
+
+ [:ensure, :uid, :gid, :home, :comment, :shell, :password, :groups].each do |property|
+ it "should have a %s property" % property do
+ user.attrclass(property).ancestors.should be_include(Puppet::Property)
+ end
+
+ it "should have documentation for its %s property" % property do
+ user.attrclass(property).doc.should be_instance_of(String)
+ end
+ end
+
+ describe "when retrieving all current values" do
+ before do
+ @user = user.create(:name => "foo", :uid => 10, :gid => 10)
+ @properties = {}
+ end
+
+ it "should return a hash containing values for all set properties" do
+ values = @user.retrieve
+ [@user.property(:uid), @user.property(:gid)].each { |property| values.should be_include(property) }
+ end
+
+ it "should set all values to :absent if the user is absent" do
+ @user.property(:ensure).expects(:retrieve).returns :absent
+ @user.property(:uid).expects(:retrieve).never
+ @user.retrieve[@user.property(:uid)].should == :absent
+ end
+
+ it "should include the result of retrieving each property's current value if the user is present" do
+ @user.property(:ensure).expects(:retrieve).returns :present
+ @user.property(:uid).expects(:retrieve).returns 15
+ @user.retrieve[@user.property(:uid)].should == 15
+ end
+ end
+
+ describe "when managing the ensure property" do
+ before do
+ @ensure = user.attrclass(:ensure).new(:resource => @resource)
+ end
+
+ it "should support a :present value" do
+ lambda { @ensure.should = :present }.should_not raise_error
+ end
+
+ it "should support an :absent value" do
+ lambda { @ensure.should = :absent }.should_not raise_error
+ end
+
+ it "should call :create on the provider when asked to sync to the :present state" do
+ @provider.expects(:create)
+ @ensure.should = :present
+ @ensure.sync
+ end
+
+ it "should call :delete on the provider when asked to sync to the :absent state" do
+ @provider.expects(:delete)
+ @ensure.should = :absent
+ @ensure.sync
+ end
+
+ describe "and determining the current state" do
+ it "should return :present when the provider indicates the user exists" do
+ @provider.expects(:exists?).returns true
+ @ensure.retrieve.should == :present
+ end
+
+ it "should return :absent when the provider indicates the user does not exist" do
+ @provider.expects(:exists?).returns false
+ @ensure.retrieve.should == :absent
+ end
+ end
+ end
+
+ describe "when managing the uid property" do
+ it "should convert number-looking strings into actual numbers" do
+ uid = user.attrclass(:uid).new(:resource => @resource)
+ uid.should = "50"
+ uid.should.must == 50
+ end
+
+ it "should support UIDs as numbers" do
+ uid = user.attrclass(:uid).new(:resource => @resource)
+ uid.should = 50
+ uid.should.must == 50
+ end
+
+ it "should :absent as a value" do
+ uid = user.attrclass(:uid).new(:resource => @resource)
+ uid.should = :absent
+ uid.should.must == :absent
+ end
+ end
+
+ describe "when managing the gid" do
+ it "should :absent as a value" do
+ gid = user.attrclass(:gid).new(:resource => @resource)
+ gid.should = :absent
+ gid.should.must == :absent
+ end
+
+ it "should convert number-looking strings into actual numbers" do
+ gid = user.attrclass(:gid).new(:resource => @resource)
+ gid.should = "50"
+ gid.should.must == 50
+ end
+ it "should support GIDs specified as integers" do
+ gid = user.attrclass(:gid).new(:resource => @resource)
+ gid.should = 50
+ gid.should.must == 50
+ end
+
+ it "should support groups specified by name" do
+ gid = user.attrclass(:gid).new(:resource => @resource)
+ gid.should = "foo"
+ gid.should.must == "foo"
+ end
+
+ describe "when syncing" do
+ before do
+ @gid = user.attrclass(:gid).new(:resource => @resource, :should => %w{foo bar})
+ end
+
+ it "should use the first found, specified group as the desired value and send it to the provider" do
+ Puppet::Util.expects(:gid).with("foo").returns nil
+ Puppet::Util.expects(:gid).with("bar").returns 500
+
+ @provider.expects(:gid=).with 500
+
+ @gid.sync
+ end
+ end
+ end
+
+ describe "when managing passwords" do
+ before do
+ @password = user.attrclass(:password).new(:resource => @resource, :should => "mypass")
+ end
+
+ it "should not include the password in the change log when adding the password" do
+ @password.change_to_s(:absent, "mypass").should_not be_include("mypass")
+ end
+ it "should not include the password in the change log when changing the password" do
+ @password.change_to_s("other", "mypass").should_not be_include("mypass")
+ end
+ end
+end
diff --git a/spec/unit/util/log.rb b/spec/unit/util/log.rb
new file mode 100755
index 000000000..aa00602a9
--- /dev/null
+++ b/spec/unit/util/log.rb
@@ -0,0 +1,153 @@
+#!/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/log'
+
+describe Puppet::Util::Log do
+ describe "instances" do
+ before do
+ Puppet::Util::Log.stubs(:newmessage)
+ end
+
+ [:level, :message, :time, :remote].each do |attr|
+ it "should have a %s attribute" % attr do
+ log = Puppet::Util::Log.new :level => :notice, :message => "A test message"
+ log.should respond_to(attr)
+ log.should respond_to(attr.to_s + "=")
+ end
+ end
+
+ it "should fail if created without a level" do
+ lambda { Puppet::Util::Log.new(:message => "A test message") }.should raise_error(ArgumentError)
+ end
+
+ it "should fail if created without a message" do
+ lambda { Puppet::Util::Log.new(:level => :notice) }.should raise_error(ArgumentError)
+ end
+
+ it "should make available the level passed in at initialization" do
+ Puppet::Util::Log.new(:level => :notice, :message => "A test message").level.should == :notice
+ end
+
+ it "should make available the message passed in at initialization" do
+ Puppet::Util::Log.new(:level => :notice, :message => "A test message").message.should == "A test message"
+ end
+
+ # LAK:NOTE I don't know why this behavior is here, I'm just testing what's in the code,
+ # at least at first.
+ it "should always convert messages to strings" do
+ Puppet::Util::Log.new(:level => :notice, :message => :foo).message.should == "foo"
+ end
+
+ it "should convert the level to a symbol if it's passed in as a string" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).level.should == :notice
+ end
+
+ it "should fail if the level is not a symbol or string" do
+ lambda { Puppet::Util::Log.new(:level => 50, :message => :foo) }.should raise_error(ArgumentError)
+ end
+
+ it "should fail if the provided level is not valid" do
+ Puppet::Util::Log.expects(:validlevel?).with(:notice).returns false
+ lambda { Puppet::Util::Log.new(:level => :notice, :message => :foo) }.should raise_error(ArgumentError)
+ end
+
+ it "should set its time to the initialization time" do
+ time = mock 'time'
+ Time.expects(:now).returns time
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).time.should equal(time)
+ end
+
+ it "should make available any passed-in tags" do
+ log = Puppet::Util::Log.new(:level => "notice", :message => :foo, :tags => %w{foo bar})
+ log.tags.should be_include("foo")
+ log.tags.should be_include("bar")
+ end
+
+ it "should use an passed-in source" do
+ Puppet::Util::Log.any_instance.expects(:source=).with "foo"
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => "foo")
+ end
+
+ it "should default to 'Puppet' as its source" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).source.should == "Puppet"
+ end
+
+ it "should register itself with Log" do
+ Puppet::Util::Log.expects(:newmessage)
+ Puppet::Util::Log.new(:level => "notice", :message => :foo)
+ end
+
+ it "should have a method for determining if a tag is present" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).should respond_to(:tagged?)
+ end
+
+ it "should match a tag if any of the tags are equivalent to the passed tag as a string" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :tags => %w{one two}).should be_tagged(:one)
+ end
+
+ it "should tag itself with its log level" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).should be_tagged(:notice)
+ end
+
+ it "should return its message when converted to a string" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).to_s.should == "foo"
+ end
+
+ it "should include its time, source, level, and message when prepared for reporting" do
+ log = Puppet::Util::Log.new(:level => "notice", :message => :foo)
+ report = log.to_report
+ report.should be_include("notice")
+ report.should be_include("foo")
+ report.should be_include(log.source)
+ report.should be_include(log.time.to_s)
+ end
+
+ it "should have a method for indicating whether it was created by a resource" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo).should respond_to(:objectsource?)
+ end
+
+ describe "when setting a source" do
+ it "should mark itself as from a Puppet resource if its source is a Puppet resource" do
+ file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs"
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file).should be_objectsource
+ end
+
+ it "should use the resource's path when its source is a resource" do
+ # Use a different path, so we don't use 'clear', which is deprecated in master
+ file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/path"
+ file.expects(:path).returns "mypath"
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file).source.should == "mypath"
+ end
+
+ it "should mark itself as from a Puppet resource if its source is a Puppet parameter" do
+ file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/parameters", :mode => "500"
+ mode = file.property(:mode)
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => mode).should be_objectsource
+ end
+
+ it "should use the resource's path when its source is a Puppet parameter" do
+ # Use a different path, so we don't use 'clear', which is deprecated in master
+ file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/path/in/parameters", :mode => "500"
+ mode = file.property(:mode)
+ mode.expects(:path).returns "mypath"
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => mode).source.should == "mypath"
+ end
+
+ it "should acquire its source's tags if its source has any" do
+ file = Puppet::Type.type(:file).create :path => "/testing/object/source/in/logs/with/tags"
+ file.tag("foo")
+ file.tag("bar")
+ log = Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => file)
+
+ log.should be_tagged("foo")
+ log.should be_tagged("bar")
+ end
+
+ it "should not set objectsource if the source is not a Parameter or Resource" do
+ Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => "mysource").should_not be_objectsource
+ end
+ end
+ end
+end
diff --git a/spec/unit/util/metric.rb b/spec/unit/util/metric.rb
new file mode 100755
index 000000000..3501aac90
--- /dev/null
+++ b/spec/unit/util/metric.rb
@@ -0,0 +1,95 @@
+#!/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/metric'
+
+describe Puppet::Util::Metric do
+ before do
+ @metric = Puppet::Util::Metric.new("foo")
+ end
+
+ it "should be aliased to Puppet::Metric" do
+ Puppet::Util::Metric.should equal(Puppet::Metric)
+ end
+
+ [:type, :name, :value, :label, :basedir].each do |name|
+ it "should have a #{name} attribute" do
+ @metric.should respond_to(name)
+ @metric.should respond_to(name.to_s + "=")
+ end
+ end
+
+ it "should default to the :rrdir as the basedir "do
+ Puppet.settings.expects(:value).with(:rrddir).returns "myrrd"
+ @metric.basedir.should == "myrrd"
+ end
+
+ it "should use any provided basedir" do
+ @metric.basedir = "foo"
+ @metric.basedir.should == "foo"
+ end
+
+ it "should require a name at initialization" do
+ lambda { Puppet::Util::Metric.new }.should raise_error(ArgumentError)
+ end
+
+ it "should always convert its name to a string" do
+ Puppet::Util::Metric.new(:foo).name.should == "foo"
+ end
+
+ it "should support a label" do
+ Puppet::Util::Metric.new("foo", "mylabel").label.should == "mylabel"
+ end
+
+ it "should autogenerate a label if none is provided" do
+ Puppet::Util::Metric.new("foo_bar").label.should == "Foo bar"
+ end
+
+ it "should have a method for adding values" do
+ @metric.should respond_to(:newvalue)
+ end
+
+ it "should have a method for returning values" do
+ @metric.should respond_to(:values)
+ end
+
+ it "should require a name and value for its values" do
+ lambda { @metric.newvalue }.should raise_error(ArgumentError)
+ end
+
+ it "should support a label for values" do
+ @metric.newvalue(:foo, 10, "label")
+ @metric.values[0][1].should == "label"
+ end
+
+ it "should autogenerate value labels if none is provided" do
+ @metric.newvalue("foo_bar", 10)
+ @metric.values[0][1].should == "Foo bar"
+ end
+
+ it "should return its values sorted by label" do
+ @metric.newvalue(:foo, 10, "b")
+ @metric.newvalue(:bar, 10, "a")
+
+ @metric.values.should == [[:bar, "a", 10], [:foo, "b", 10]]
+ end
+
+ it "should use an array indexer method to retrieve individual values" do
+ @metric.newvalue(:foo, 10)
+ @metric[:foo].should == 10
+ end
+
+ it "should return nil if the named value cannot be found" do
+ @metric[:foo].should be_nil
+ end
+
+ # LAK: I'm not taking the time to develop these tests right now.
+ # I expect they should actually be extracted into a separate class
+ # anyway.
+ it "should be able to graph metrics using RRDTool"
+
+ it "should be able to create a new RRDTool database"
+
+ it "should be able to store metrics into an RRDTool database"
+end
diff --git a/spec/unit/util/posix.rb b/spec/unit/util/posix.rb
new file mode 100755
index 000000000..95a5608bd
--- /dev/null
+++ b/spec/unit/util/posix.rb
@@ -0,0 +1,256 @@
+#!/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/posix'
+
+class PosixTest
+ include Puppet::Util::POSIX
+end
+
+describe Puppet::Util::POSIX do
+ before do
+ @posix = PosixTest.new
+ end
+
+ [:group, :gr].each do |name|
+ it "should return :gid as the field for %s" % name do
+ @posix.idfield(name).should == :gid
+ end
+
+ it "should return :getgrgid as the id method for %s" % name do
+ @posix.methodbyid(name).should == :getgrgid
+ end
+
+ it "should return :getgrnam as the name method for %s" % name do
+ @posix.methodbyname(name).should == :getgrnam
+ end
+ end
+
+ [:user, :pw, :passwd].each do |name|
+ it "should return :uid as the field for %s" % name do
+ @posix.idfield(name).should == :uid
+ end
+
+ it "should return :getpwuid as the id method for %s" % name do
+ @posix.methodbyid(name).should == :getpwuid
+ end
+
+ it "should return :getpwnam as the name method for %s" % name do
+ @posix.methodbyname(name).should == :getpwnam
+ end
+ end
+
+ describe "when retrieving a posix field" do
+ before do
+ @thing = stub 'thing', :field => "asdf"
+ end
+
+ it "should fail if no id was passed" do
+ lambda { @posix.get_posix_field("asdf", "bar", nil) }.should raise_error(Puppet::DevError)
+ end
+
+ describe "and the id is an integer" do
+ it "should log an error and return nil if the specified id is greater than the maximum allowed ID" do
+ Puppet.settings.expects(:value).with(:maximum_uid).returns 100
+ Puppet.expects(:err)
+
+ @posix.get_posix_field("asdf", "bar", 200).should be_nil
+ end
+
+ it "should use the method return by :methodbyid and return the specified field" do
+ Etc.expects(:getgrgid).returns @thing
+
+ @thing.expects(:field).returns "myval"
+
+ @posix.get_posix_field(:gr, :field, 200).should == "myval"
+ end
+
+ it "should return nil if the method throws an exception" do
+ Etc.expects(:getgrgid).raises ArgumentError
+
+ @thing.expects(:field).never
+
+ @posix.get_posix_field(:gr, :field, 200).should be_nil
+ end
+ end
+
+ describe "and the id is not an integer" do
+ it "should use the method return by :methodbyid and return the specified field" do
+ Etc.expects(:getgrnam).returns @thing
+
+ @thing.expects(:field).returns "myval"
+
+ @posix.get_posix_field(:gr, :field, "asdf").should == "myval"
+ end
+
+ it "should return nil if the method throws an exception" do
+ Etc.expects(:getgrnam).raises ArgumentError
+
+ @thing.expects(:field).never
+
+ @posix.get_posix_field(:gr, :field, "asdf").should be_nil
+ end
+ end
+ end
+
+ describe "when returning the gid" do
+ before do
+ @posix.stubs(:get_posix_field)
+ end
+
+ describe "and the group is an integer" do
+ it "should convert integers specified as a string into an integer" do
+ @posix.expects(:get_posix_field).with(:group, :name, 100)
+
+ @posix.gid("100")
+ end
+
+ it "should look up the name for the group" do
+ @posix.expects(:get_posix_field).with(:group, :name, 100)
+
+ @posix.gid(100)
+ end
+
+ it "should return nil if the group cannot be found" do
+ @posix.expects(:get_posix_field).once.returns nil
+ @posix.expects(:search_posix_field).never
+
+ @posix.gid(100).should be_nil
+ end
+
+ it "should use the found name to look up the id" do
+ @posix.expects(:get_posix_field).with(:group, :name, 100).returns "asdf"
+ @posix.expects(:get_posix_field).with(:group, :gid, "asdf").returns 100
+
+ @posix.gid(100).should == 100
+ end
+
+ # LAK: This is because some platforms have a broken Etc module that always return
+ # the same group.
+ it "should use :search_posix_field if the discovered id does not match the passed-in id" do
+ @posix.expects(:get_posix_field).with(:group, :name, 100).returns "asdf"
+ @posix.expects(:get_posix_field).with(:group, :gid, "asdf").returns 50
+
+ @posix.expects(:search_posix_field).with(:group, :gid, 100).returns "asdf"
+
+ @posix.gid(100).should == "asdf"
+ end
+ end
+
+ describe "and the group is a string" do
+ it "should look up the gid for the group" do
+ @posix.expects(:get_posix_field).with(:group, :gid, "asdf")
+
+ @posix.gid("asdf")
+ end
+
+ it "should return nil if the group cannot be found" do
+ @posix.expects(:get_posix_field).once.returns nil
+ @posix.expects(:search_posix_field).never
+
+ @posix.gid("asdf").should be_nil
+ end
+
+ it "should use the found gid to look up the nam" do
+ @posix.expects(:get_posix_field).with(:group, :gid, "asdf").returns 100
+ @posix.expects(:get_posix_field).with(:group, :name, 100).returns "asdf"
+
+ @posix.gid("asdf").should == 100
+ end
+
+ it "should use :search_posix_field if the discovered name does not match the passed-in name" do
+ @posix.expects(:get_posix_field).with(:group, :gid, "asdf").returns 100
+ @posix.expects(:get_posix_field).with(:group, :name, 100).returns "boo"
+
+ @posix.expects(:search_posix_field).with(:group, :gid, "asdf").returns "asdf"
+
+ @posix.gid("asdf").should == "asdf"
+ end
+ end
+ end
+
+ describe "when returning the uid" do
+ before do
+ @posix.stubs(:get_posix_field)
+ end
+
+ describe "and the group is an integer" do
+ it "should convert integers specified as a string into an integer" do
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100)
+
+ @posix.uid("100")
+ end
+
+ it "should look up the name for the group" do
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100)
+
+ @posix.uid(100)
+ end
+
+ it "should return nil if the group cannot be found" do
+ @posix.expects(:get_posix_field).once.returns nil
+ @posix.expects(:search_posix_field).never
+
+ @posix.uid(100).should be_nil
+ end
+
+ it "should use the found name to look up the id" do
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100).returns "asdf"
+ @posix.expects(:get_posix_field).with(:passwd, :uid, "asdf").returns 100
+
+ @posix.uid(100).should == 100
+ end
+
+ # LAK: This is because some platforms have a broken Etc module that always return
+ # the same group.
+ it "should use :search_posix_field if the discovered id does not match the passed-in id" do
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100).returns "asdf"
+ @posix.expects(:get_posix_field).with(:passwd, :uid, "asdf").returns 50
+
+ @posix.expects(:search_posix_field).with(:passwd, :uid, 100).returns "asdf"
+
+ @posix.uid(100).should == "asdf"
+ end
+ end
+
+ describe "and the group is a string" do
+ it "should look up the uid for the group" do
+ @posix.expects(:get_posix_field).with(:passwd, :uid, "asdf")
+
+ @posix.uid("asdf")
+ end
+
+ it "should return nil if the group cannot be found" do
+ @posix.expects(:get_posix_field).once.returns nil
+ @posix.expects(:search_posix_field).never
+
+ @posix.uid("asdf").should be_nil
+ end
+
+ it "should use the found uid to look up the nam" do
+ @posix.expects(:get_posix_field).with(:passwd, :uid, "asdf").returns 100
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100).returns "asdf"
+
+ @posix.uid("asdf").should == 100
+ end
+
+ it "should use :search_posix_field if the discovered name does not match the passed-in name" do
+ @posix.expects(:get_posix_field).with(:passwd, :uid, "asdf").returns 100
+ @posix.expects(:get_posix_field).with(:passwd, :name, 100).returns "boo"
+
+ @posix.expects(:search_posix_field).with(:passwd, :uid, "asdf").returns "asdf"
+
+ @posix.uid("asdf").should == "asdf"
+ end
+ end
+ end
+
+ it "should be able to iteratively search for posix values" do
+ @posix.should respond_to(:search_posix_field)
+ end
+
+ describe "when searching for posix values iteratively" do
+ it "should iterate across all of the structs returned by Etc and return the appropriate field from the first matching value"
+ end
+end
diff --git a/spec/unit/util/selinux.rb b/spec/unit/util/selinux.rb
new file mode 100644
index 000000000..1718404e8
--- /dev/null
+++ b/spec/unit/util/selinux.rb
@@ -0,0 +1,174 @@
+#!/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/selinux'
+include Puppet::Util::SELinux
+
+describe Puppet::Util::SELinux do
+
+ describe "selinux_support?" do
+ it "should return :true if this system has SELinux enabled" do
+ FileTest.expects(:exists?).with("/selinux/enforce").returns true
+ selinux_support?.should be_true
+ end
+
+ it "should return :false if this system lacks SELinux" do
+ FileTest.expects(:exists?).with("/selinux/enforce").returns false
+ selinux_support?.should be_false
+ end
+ end
+
+ describe "get_selinux_current_context" do
+ it "should return nil if no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ get_selinux_current_context("/foo").should be_nil
+ end
+
+ it "should return a context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").yields ["user_u:role_r:type_t:s0\n"]
+ get_selinux_current_context("/foo").should == "user_u:role_r:type_t:s0"
+ end
+
+ it "should return nil if an exception is raised calling stat" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").raises(Puppet::ExecutionFailure, 'error')
+ get_selinux_current_context("/foo").should be_nil
+ end
+
+ it "should return nil if stat finds an unlabeled file" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:execpipe).with("stat -c %C /foo").yields ["(null)\n"]
+ get_selinux_current_context("/foo").should be_nil
+ end
+ end
+
+ describe "get_selinux_default_context" do
+ it "should return nil if no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ get_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return nil if matchpathcon is not executable" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns false
+ get_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return a context if a default context exists" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns true
+ self.expects(:execpipe).with("/usr/sbin/matchpathcon /foo").yields ["/foo\tuser_u:role_r:type_t:s0\n"]
+ get_selinux_default_context("/foo").should == "user_u:role_r:type_t:s0"
+ end
+
+ it "should return nil if an exception is raised calling matchpathcon" do
+ self.expects(:selinux_support?).returns true
+ FileTest.expects(:executable?).with("/usr/sbin/matchpathcon").returns true
+ self.expects(:execpipe).with("/usr/sbin/matchpathcon /foo").raises(Puppet::ExecutionFailure, 'error')
+ get_selinux_default_context("/foo").should be_nil
+ end
+ end
+
+ describe "parse_selinux_context" do
+ it "should return nil if no context is passed" do
+ parse_selinux_context(:seluser, nil).should be_nil
+ end
+
+ it "should return nil if the context is 'unlabeled'" do
+ parse_selinux_context(:seluser, "unlabeled").should be_nil
+ end
+
+ it "should return the user type when called with :seluser" do
+ parse_selinux_context(:seluser, "user_u:role_r:type_t:s0").should == "user_u"
+ end
+
+ it "should return the role type when called with :selrole" do
+ parse_selinux_context(:selrole, "user_u:role_r:type_t:s0").should == "role_r"
+ end
+
+ it "should return the type type when called with :seltype" do
+ parse_selinux_context(:seltype, "user_u:role_r:type_t:s0").should == "type_t"
+ end
+
+ it "should return nil for :selrange when no range is returned" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t").should be_nil
+ end
+
+ it "should return the range type when called with :selrange" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t:s0").should == "s0"
+ end
+
+ describe "with a variety of SELinux range formats" do
+ ['s0', 's0:c3', 's0:c3.c123', 's0:c3,c5,c8', 'TopSecret', 'TopSecret,Classified', 'Patient_Record'].each do |range|
+ it "should parse range '#{range}'" do
+ parse_selinux_context(:selrange, "user_u:role_r:type_t:#{range}").should == range
+ end
+ end
+ end
+ end
+
+ describe "set_selinux_context" do
+ it "should return nil if there is no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_nil
+ end
+
+ it "should use chcon to set a context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon user_u:role_r:type_t:s0 /foo").returns 0
+ set_selinux_context("/foo", "user_u:role_r:type_t:s0").should be_true
+ end
+
+ it "should use chcon to set user_u user context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -u user_u /foo").returns 0
+ set_selinux_context("/foo", "user_u", :seluser).should be_true
+ end
+
+ it "should use chcon to set role_r role context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -r role_r /foo").returns 0
+ set_selinux_context("/foo", "role_r", :selrole).should be_true
+ end
+
+ it "should use chcon to set type_t type context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -t type_t /foo").returns 0
+ set_selinux_context("/foo", "type_t", :seltype).should be_true
+ end
+
+ it "should use chcon to set s0:c3,c5 range context" do
+ self.expects(:selinux_support?).returns true
+ self.expects(:system).with("chcon -l s0:c3,c5 /foo").returns 0
+ set_selinux_context("/foo", "s0:c3,c5", :selrange).should be_true
+ end
+ end
+
+ describe "set_selinux_default_context" do
+ it "should return nil if there is no SELinux support" do
+ self.expects(:selinux_support?).returns false
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should return nil if no default context exists" do
+ self.expects(:get_selinux_default_context).with("/foo").returns nil
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should do nothing and return nil if the current context matches the default context" do
+ self.expects(:get_selinux_default_context).with("/foo").returns "user_u:role_r:type_t"
+ self.expects(:get_selinux_current_context).with("/foo").returns "user_u:role_r:type_t"
+ set_selinux_default_context("/foo").should be_nil
+ end
+
+ it "should set and return the default context if current and default do not match" do
+ self.expects(:get_selinux_default_context).with("/foo").returns "user_u:role_r:type_t"
+ self.expects(:get_selinux_current_context).with("/foo").returns "olduser_u:role_r:type_t"
+ self.expects(:set_selinux_context).with("/foo", "user_u:role_r:type_t").returns true
+ set_selinux_default_context("/foo").should == "user_u:role_r:type_t"
+ end
+ end
+
+end
diff --git a/spec/unit/util/settings.rb b/spec/unit/util/settings.rb
index 2a3c2afc7..313042d65 100755
--- a/spec/unit/util/settings.rb
+++ b/spec/unit/util/settings.rb
@@ -249,6 +249,12 @@ describe Puppet::Util::Settings do
@settings.value(:one, "env").should == "envval"
end
+ it "should interpolate found values using the current environment" do
+ @settings.setdefaults :main, :myval => ["$environment/foo", "mydocs"]
+
+ @settings.value(:myval, "myenv").should == "myenv/foo"
+ end
+
it "should return values in a specified environment before values in the main or name sections" do
text = "[env]\none = envval\n[main]\none = mainval\n[myname]\none = nameval\n"
file = "/some/file"
@@ -790,6 +796,7 @@ describe Puppet::Util::Settings do
end
it "should return false if a config param is not found" do
+ @settings.stubs :puts
@settings.stubs(:value).with(:configprint).returns("something")
@settings.stubs(:include?).with("something").returns(false)
@settings.print_configs.should be_false
@@ -797,6 +804,10 @@ describe Puppet::Util::Settings do
end
describe "when genconfig is true" do
+ before do
+ @settings.stubs :puts
+ end
+
it "should call to_config" do
@settings.stubs(:value).with(:genconfig).returns(true)
@settings.expects(:to_config)
@@ -811,6 +822,10 @@ describe Puppet::Util::Settings do
end
describe "when genmanifest is true" do
+ before do
+ @settings.stubs :puts
+ end
+
it "should call to_config" do
@settings.stubs(:value).with(:genmanifest).returns(true)
@settings.expects(:to_manifest)
diff --git a/spec/unit/util/user_attr.rb b/spec/unit/util/user_attr.rb
new file mode 100644
index 000000000..57787b1a6
--- /dev/null
+++ b/spec/unit/util/user_attr.rb
@@ -0,0 +1,47 @@
+#!/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/user_attr'
+
+describe UserAttr do
+ before do
+ user_attr = ["foo::::type=role", "bar::::type=normal;profile=foobar"]
+ File.stubs(:readlines).returns(user_attr)
+ end
+
+ describe "when getting attributes by name" do
+ it "should return nil if there is no entry for that name" do
+ UserAttr.get_attributes_by_name('baz').should == nil
+ end
+
+ it "should return a hash if there is an entry in /etc/user_attr" do
+ UserAttr.get_attributes_by_name('foo').class.should == Hash
+ end
+
+ it "should return a hash with the name value from /etc/user_attr" do
+ UserAttr.get_attributes_by_name('foo')[:name].should == 'foo'
+ end
+
+ #this test is contrived
+ #there are a bunch of possible parameters that could be in the hash
+ #the role/normal is just a the convention of the file
+ describe "when the name is a role" do
+ it "should contain :type = role" do
+ UserAttr.get_attributes_by_name('foo')[:type].should == 'role'
+ end
+ end
+
+ describe "when the name is not a role" do
+ it "should contain :type = normal" do
+ UserAttr.get_attributes_by_name('bar')[:type].should == 'normal'
+ end
+ end
+
+ describe "when the name has more attributes" do
+ it "should contain all the attributes" do
+ UserAttr.get_attributes_by_name('bar')[:profile].should == 'foobar'
+ end
+ end
+ end
+end
diff --git a/test/data/providers/ssh_authorized_key/parsed/authorized_keys1 b/test/data/providers/ssh_authorized_key/parsed/authorized_keys1
new file mode 100644
index 000000000..7aa0647ca
--- /dev/null
+++ b/test/data/providers/ssh_authorized_key/parsed/authorized_keys1
@@ -0,0 +1,3 @@
+1024 35 167576894966720957580065952882142495543043407324667405194097438434880798807651864847570827148390962746149410384891026772700627764845955493549511618975091512997118590589399665757714186775228807376424903966072778732134483862302766419277581465932186641863495699668069439475320990051723279127881281145164415361627 francois@korn
+2048 35 27332429396020032283276339339051507284036000350350092862949624519871013308460312287866673933080560923221560798334008554200019645416448528663000202951887890525621015333936122655294782671001073795264378070156670395703161543893088138531854776737799752600933431638059304355933305878665812555436198516842364330938321746086651639330436648850787370397302524667456837036413634152938122227368132322078811602953517461933179827432019932348409533535942749570969101453655028606209719023224268890314608444789012688070463327764203306501923404494017305972543000091038543051645924928018568725584728655193415567703220002707737714942757 francois@korn
+from="192.168.1.1",command="/bin/false",no-pty,no-port-forwarding 2048 35 27332429396020032283276339339051507284036000350350092862949624519871013308460312287866673933080560923221560798334008554200019645416448528663000202951887890525621015333936122655294782671001073795264378070156670395703161543893088138531854776737799752600933431638059304355933305878665812555436198516842364330938321746086651639330436648850787370397302524667456837036413634152938122227368132322078811602953517461933179827432019932348409533535942749570969101453655028606209719023224268890314608444789012688070463327764203306501923404494017305972543000091038543051645924928018568725584728655193415567703220002707737714942757 francois@korn
diff --git a/test/data/snippets/arithmetic_expression.pp b/test/data/snippets/arithmetic_expression.pp
new file mode 100644
index 000000000..aae98a4db
--- /dev/null
+++ b/test/data/snippets/arithmetic_expression.pp
@@ -0,0 +1,8 @@
+
+$one = 1.30
+$two = 2.034e-2
+
+$result = ((( $two + 2) / $one) + 4 * 5.45) - (6 << 7) + (0x800 + -9)
+
+
+notice("result is $result == 1295.87692307692") \ No newline at end of file
diff --git a/test/data/snippets/emptyifelse.pp b/test/data/snippets/emptyifelse.pp
new file mode 100644
index 000000000..598b486ac
--- /dev/null
+++ b/test/data/snippets/emptyifelse.pp
@@ -0,0 +1,9 @@
+
+if false {
+} else {
+ # nothing here
+}
+
+if true {
+ # still nothing
+}
diff --git a/test/data/snippets/ifexpression.rb b/test/data/snippets/ifexpression.rb
new file mode 100644
index 000000000..eea3b855b
--- /dev/null
+++ b/test/data/snippets/ifexpression.rb
@@ -0,0 +1,6 @@
+$one = 1
+$two = 2
+
+if ($one < $two) and (($two < 3) or ($two == 2)) {
+ notice("True!")
+}
diff --git a/test/language/ast/resource_reference.rb b/test/language/ast/resource_reference.rb
index 1f554d90f..75cb53c12 100755
--- a/test/language/ast/resource_reference.rb
+++ b/test/language/ast/resource_reference.rb
@@ -23,34 +23,6 @@ class TestASTResourceReference < Test::Unit::TestCase
@parser = @scope.compiler.parser
end
- def test_evaluate
- @parser.newdefine "one::two"
- @parser.newdefine "one-two"
- [%w{File /tmp/yay}, %w{One::Two three}, %w{One-two three}].each do |type, title|
- ref = newref(type, title)
-
- evaled = nil
- assert_nothing_raised("Could not evaluate resource ref") do
- evaled = ref.evaluate(@scope)
- end
-
- assert_equal(type, evaled.type, "Type did not translate correctly")
- assert_equal(title, evaled.title, "Title did not translate correctly")
- end
- end
-
- def test_finding_classes_for_reference
- @parser.newclass "one"
- ref = newref("Class", "one")
- evaled = nil
- assert_nothing_raised("Could not evaluate resource ref") do
- evaled = ref.evaluate(@scope)
- end
-
- assert_equal("Class", evaled.type, "Did not set type to 'class'")
- assert_equal("one", evaled.title, "Did not look up class corectly")
- end
-
# Related to #706, make sure resource references correctly translate to qualified types.
def test_scoped_references
@parser.newdefine "one"
diff --git a/test/language/functions.rb b/test/language/functions.rb
index 50a61a148..d9a1a561d 100755
--- a/test/language/functions.rb
+++ b/test/language/functions.rb
@@ -278,7 +278,7 @@ class TestLangFunctions < Test::Unit::TestCase
file = tempfile()
Puppet[:code] = %{file { "#{file}": content => template("#{template}") }}
- Puppet[:environments] = "yay"
+ Puppet[:environment] = "yay"
interp = Puppet::Parser::Interpreter.new
node = mknode
node.stubs(:environment).returns("yay")
diff --git a/test/lib/puppettest/reporttesting.rb b/test/lib/puppettest/reporttesting.rb
index 9b1764cf6..4d88c3cfc 100644
--- a/test/lib/puppettest/reporttesting.rb
+++ b/test/lib/puppettest/reporttesting.rb
@@ -6,8 +6,6 @@ module PuppetTest::Reporttesting
3.times { |i|
# We have to use warning so that the logs always happen
log = Puppet.warning("Report test message %s" % i)
- log.tags = %w{a list of tags}
- log.tags << "tag%s" % i
report.newlog(log)
}
diff --git a/test/lib/puppettest/runnable_test.rb b/test/lib/puppettest/runnable_test.rb
index e3cde5052..6dab1b743 100644
--- a/test/lib/puppettest/runnable_test.rb
+++ b/test/lib/puppettest/runnable_test.rb
@@ -12,6 +12,8 @@ module PuppetTest
end
end
+ attr_reader :messages
+
# Evaluate all of our tests to see if any of them are false
# and thus whether this test is considered not runnable.
def runnable?
diff --git a/test/network/client/master.rb b/test/network/client/master.rb
index 0c1405217..90f747d94 100755
--- a/test/network/client/master.rb
+++ b/test/network/client/master.rb
@@ -402,12 +402,9 @@ end
client.send(:splay)
end
- time = Puppet::Util::Storage.cache(:configuration)[:splay_time]
- assert(time, "Splay time was not cached")
-
# Now try it again
client = mkclient
- client.expects(:sleep).with(time)
+ client.expects(:sleep)
assert_nothing_raised("Failed to call sleep when splay is true with a cached value") do
client.send(:splay)
@@ -419,8 +416,7 @@ end
assert_equal(facts["environment"], Puppet[:environment], "Did not add environment to client facts")
# Now set it to a real value
- Puppet[:environments] = "something,else"
- Puppet[:environment] = "something"
+ Puppet[:environment] = "something"
facts = Puppet::Network::Client::Master.facts
assert_equal(facts["environment"], Puppet[:environment], "Did not add environment to client facts")
end
diff --git a/test/network/handler/fileserver.rb b/test/network/handler/fileserver.rb
index a705dbf4b..873657e5d 100755
--- a/test/network/handler/fileserver.rb
+++ b/test/network/handler/fileserver.rb
@@ -437,6 +437,14 @@ class TestFileServer < Test::Unit::TestCase
assert_nil(retval, "Description of non-existent mounts returned a value")
end
+ def test_describe_does_not_fail_when_mount_does_not_find_file
+ server = Puppet::Network::Handler.fileserver.new(:Local => true, :Config => false)
+
+ assert_nothing_raised("Failed when describing missing plugins") do
+ server.describe "/plugins"
+ end
+ end
+
# test that our config file is parsing and working as planned
def test_configfile
server = nil
diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb
index d342af88c..654404ae5 100755
--- a/test/network/handler/master.rb
+++ b/test/network/handler/master.rb
@@ -25,7 +25,9 @@ class TestMaster < Test::Unit::TestCase
now1 = mock 'now1'
Time.expects(:now).returns(now1)
- assert_equal(@master.freshness, now1, "Did not return current time as freshness")
+ now1.expects(:to_i).returns 10
+
+ assert_equal(@master.freshness, 10, "Did not return current time as freshness")
end
def test_hostname_is_used_if_client_is_missing
diff --git a/test/other/report.rb b/test/other/report.rb
index 9894e2a8d..9d0bb4852 100755
--- a/test/other/report.rb
+++ b/test/other/report.rb
@@ -21,7 +21,7 @@ class TestReports < Test::Unit::TestCase
# Make every third file
File.open(file, "w") { |f| f.puts "" } if i % 3 == 0
- objects << Puppet::Type.newfile(
+ objects << Puppet::Type.type(:file).create(
:path => file,
:ensure => "file"
)
@@ -44,7 +44,7 @@ class TestReports < Test::Unit::TestCase
}
# Now make a file for testing logging
- file = Puppet::Type.newfile(:path => tempfile(), :ensure => "file")
+ file = Puppet::Type.type(:file).create(:path => tempfile(), :ensure => "file")
file.finish
log = nil
@@ -91,8 +91,6 @@ class TestReports < Test::Unit::TestCase
3.times { |i|
log = Puppet.warning("Report test message %s" % i)
- log.tags = %w{a list of tags}
- log.tags << "tag%s" % i
report.newlog(log)
}
diff --git a/test/other/transactions.rb b/test/other/transactions.rb
index 7f42bb6f4..b1dbaed92 100755
--- a/test/other/transactions.rb
+++ b/test/other/transactions.rb
@@ -248,7 +248,7 @@ class TestTransactions < Test::Unit::TestCase
assert_nothing_raised() {
check.each { |property|
- value = file.value(property)
+ value = file.property(property).retrieve
assert(value)
properties[property] = value
}
diff --git a/test/ral/providers/group.rb b/test/ral/providers/group.rb
index 18b0866b9..6479b4a12 100755
--- a/test/ral/providers/group.rb
+++ b/test/ral/providers/group.rb
@@ -30,14 +30,18 @@ class TestGroupProvider < Test::Unit::TestCase
end
def mkgroup(name, hash = {})
- fakeresource = fakeresource(:group, name)
+ fakeresource = stub 'group', :allowdupe? => false, :name => name
+ fakeresource.stubs(:[]).returns nil
+ fakeresource.stubs(:should).returns nil
+ fakeresource.stubs(:[]).with(:name).returns name
+ hash.each do |name, val|
+ fakeresource.stubs(:should).with(name).returns val
+ fakeresource.stubs(:[]).with(name).returns val
+ end
group = nil
assert_nothing_raised {
group = @provider.new(fakeresource)
}
- hash.each do |name, val|
- fakeresource[name] = val
- end
assert(group, "Could not create provider group")
return group
@@ -108,19 +112,19 @@ class TestGroupProvider < Test::Unit::TestCase
def attrtest_ensure(group)
old = group.ensure
assert_nothing_raised {
- group.ensure = :absent
+ group.delete
}
assert(!group.exists?, "Group was not deleted")
assert_nothing_raised {
- group.ensure = :present
+ group.create
}
assert(group.exists?, "Group was not created")
unless old == :present
assert_nothing_raised {
- group.ensure = old
+ group.delete
}
end
end
@@ -211,7 +215,6 @@ class TestGroupProvider < Test::Unit::TestCase
unless Facter["operatingsystem"].value == "FreeBSD"
def test_duplicateIDs
group1 = mkgroup("group1", :gid => 125)
- group2 = mkgroup("group2", :gid => 125)
@@tmpgroups << "group1"
@@tmpgroups << "group2"
@@ -222,16 +225,14 @@ class TestGroupProvider < Test::Unit::TestCase
# Not all OSes fail here, so we can't test that it doesn't work with
# it off, only that it does work with it on.
- assert_nothing_raised {
- group2.resource[:allowdupe] = :true
- }
+ group2 = mkgroup("group2", :gid => 125)
+ group2.resource.stubs(:allowdupe?).returns true
# Now create the second group
assert_nothing_raised {
group2.create
}
- assert_equal(:present, group2.ensure,
- "Group did not get created")
+ assert_equal(:present, group2.ensure, "Group did not get created")
end
end
else
diff --git a/test/ral/providers/package.rb b/test/ral/providers/package.rb
index f2d28d0f0..3b61c1abd 100755
--- a/test/ral/providers/package.rb
+++ b/test/ral/providers/package.rb
@@ -244,36 +244,5 @@ class TestPackageProvider < Test::Unit::TestCase
pkg[:adminfile] = "/usr/local/pkg/admin_file"
end
end
-
- # Make sure providers throw an error when you tell them to install a
- # non-existent package.
- def test_no_such_package
- Puppet::Type.type(:package).suitableprovider.each do |provider|
- assert_raise(ArgumentError, Puppet::Error, Puppet::ExecutionFailure,
- "Successfully installed nonexistent package with %s" % provider.name) {
- pkg = Puppet::Type.newpackage :name => "nosuch%s" % provider.name.to_s,
- :provider => provider.name
- provider = pkg.provider
- provider.install
- }
- end
- end
-
- # Make sure all of the suitable providers on our platform can successfully
- # list.
- def test_instances
- Puppet::Type.type(:package).suitableprovider.each do |provider|
- result = nil
- assert_nothing_raised("Could not list %s packages" % provider.name) do
- result = provider.instances
- end
- result.each do |pkg|
- assert_instance_of(provider, pkg,
- "%s returned non-provider" % provider.name)
- assert_equal(provider.name, pkg.class.name,
- "Provider %s returned an instance of a different provider" % provider.name)
- end
- end
- end
end
diff --git a/test/ral/providers/package/apt.rb b/test/ral/providers/package/apt.rb
deleted file mode 100755
index f4fb1a95c..000000000
--- a/test/ral/providers/package/apt.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../../lib/puppettest'
-
-require 'mocha'
-
-class AptPackageProviderTest < PuppetTest::TestCase
- confine "Apt package provider missing" =>
- Puppet::Type.type(:package).provider(:apt).suitable?
-
- def setup
- super
- @type = Puppet::Type.type(:package)
- end
-
- def test_install
- pkg = @type.create :name => 'faff',
- :provider => :apt,
- :ensure => :present,
- :source => "/tmp/faff.deb"
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).returns(
- "deinstall ok config-files faff 1.2.3-1\n"
- ).times(1)
-
- pkg.provider.expects(
- :aptget
- ).with(
- '-q',
- '-y',
- '-o',
- 'DPkg::Options::=--force-confold',
- :install,
- 'faff'
- ).returns(0)
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
- def test_purge
- pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).returns(
- "install ok installed faff 1.2.3-1\n"
- ).times(1)
- pkg.provider.expects(
- :aptget
- ).with(
- '-y',
- '-q',
- 'remove',
- '--purge',
- 'faff'
- ).returns(0)
- pkg.provider.expects(
- :dpkg
- ).with(
- '--purge',
- 'faff'
- ).returns(0)
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
- def test_dont_try_to_purge_if_already_purged
- pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).raises(
- Puppet::ExecutionFailure,
- "No packages found matching faff.\n"
- ).times(1)
- pkg.provider.expects(
- :aptget
- ).never
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
- def test_dont_try_to_purge_if_already_purged_and_we_want_it_absent
- pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :absent
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).raises(
- Puppet::ExecutionFailure,
- "No packages found matching faff.\n"
- ).times(1)
- pkg.provider.expects(
- :aptget
- ).never
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
- def test_make_sure_we_purge_if_package_still_has_conffiles
- pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).returns(
- "deinstall ok config-files faff 1.2.3-1\n"
- ).times(1)
- pkg.provider.expects(
- :aptget
- ).with(
- '-y',
- '-q',
- 'remove',
- '--purge',
- 'faff'
- ).returns(0)
- pkg.provider.expects(
- :dpkg
- ).with(
- '--purge',
- 'faff'
- ).returns(0)
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
-
- def test_latest
- pkg = @type.create :name => 'base-files', :provider => :apt
-
- assert(pkg, "did not create pkg")
- status = pkg.provider.query
- assert(status, "base-files is not installed")
- assert(status[:ensure] != :absent, "base-files is not installed")
-
- latest = nil
- assert_nothing_raised("Could not call latest") do
- latest = pkg.provider.latest
- end
- assert(latest, "Could not get latest value from apt")
- end
-end
-
diff --git a/test/ral/providers/package/aptitude.rb b/test/ral/providers/package/aptitude.rb
index f8edcebde..881f54047 100755
--- a/test/ral/providers/package/aptitude.rb
+++ b/test/ral/providers/package/aptitude.rb
@@ -41,7 +41,6 @@ class AptitudePackageProviderTest < PuppetTest::TestCase
).returns(0)
pkg.evaluate.each { |state|
- state.transaction = self
state.forward
}
end
@@ -67,6 +66,6 @@ class AptitudePackageProviderTest < PuppetTest::TestCase
'faff'
).returns(0)
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ pkg.evaluate.each { |state| state.forward }
end
end
diff --git a/test/ral/providers/package/aptrpm.rb b/test/ral/providers/package/aptrpm.rb
index c005ee5a6..32e0ea6e5 100755
--- a/test/ral/providers/package/aptrpm.rb
+++ b/test/ral/providers/package/aptrpm.rb
@@ -39,7 +39,7 @@ class AptrpmPackageProviderTest < PuppetTest::TestCase
'faff'
).returns(0)
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ pkg.evaluate.each { |state| state.forward }
end
def test_uninstall
@@ -66,7 +66,7 @@ class AptrpmPackageProviderTest < PuppetTest::TestCase
'faff'
).returns(0)
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ pkg.evaluate.each { |state| state.forward }
end
# LAK: I don't know where this test will ever return true..
diff --git a/test/ral/providers/package/dpkg.rb b/test/ral/providers/package/dpkg.rb
deleted file mode 100755
index 7e4427584..000000000
--- a/test/ral/providers/package/dpkg.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../../lib/puppettest'
-
-require 'mocha'
-
-class DpkgPackageProviderTest < PuppetTest::TestCase
- confine "dpkg package provider missing" =>
- Puppet::Type.type(:package).provider(:dpkg).suitable?
- def setup
- super
- @type = Puppet::Type.type(:package)
- end
-
- def test_install
- pkg = @type.create :name => 'faff',
- :provider => :dpkg,
- :ensure => :present,
- :source => "/tmp/faff.deb"
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).returns(
- "deinstall ok config-files faff 1.2.3-1\n"
- ).times(1)
-
- pkg.provider.expects(
- :dpkg
- ).with(
- '-i',
- '/tmp/faff.deb'
- ).returns(0)
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-
- def test_purge
- pkg = @type.create :name => 'faff', :provider => :dpkg, :ensure => :purged
-
- pkg.provider.expects(
- :dpkgquery
- ).with(
- '-W',
- '--showformat',
- '${Status} ${Package} ${Version}\n',
- 'faff'
- ).returns(
- "install ok installed faff 1.2.3-1\n"
- ).times(1)
- pkg.provider.expects(
- :dpkg
- ).with(
- '--purge',
- 'faff'
- ).returns(0)
-
- pkg.evaluate.each { |state| state.transaction = self; state.forward }
- end
-end
diff --git a/test/ral/providers/user.rb b/test/ral/providers/user.rb
index 0651d6c74..4df89583b 100755
--- a/test/ral/providers/user.rb
+++ b/test/ral/providers/user.rb
@@ -214,20 +214,20 @@ class TestUserProvider < Test::Unit::TestCase
def attrtest_ensure(user)
old = user.ensure
assert_nothing_raised {
- user.ensure = :absent
+ user.delete
}
assert(missing?(user.name), "User is still present")
assert_nothing_raised {
- user.ensure = :present
+ user.create
}
assert(!missing?(user.name), "User is absent")
assert_nothing_raised {
- user.ensure = :absent
+ user.delete
}
unless old == :absent
- user.ensure = old
+ user.create
end
end
@@ -398,10 +398,10 @@ class TestUserProvider < Test::Unit::TestCase
# Some tests to verify that groups work correctly startig from nothing
# Remove our user
- user.ensure = :absent
+ user.delete
# And add it again
- user.ensure = :present
+ user.create
# Make sure that the group list is added at creation time.
# This is necessary because we don't have default fakedata for groups.
@@ -498,8 +498,8 @@ class TestUserProvider < Test::Unit::TestCase
user2.resource[:uid] = 125
cleanup do
- user1.ensure = :absent
- user2.ensure = :absent
+ user1.delete
+ user2.delete
end
# Not all OSes fail here, so we can't test that it doesn't work with
diff --git a/test/ral/type/filesources.rb b/test/ral/type/filesources.rb
index 77b598187..24bc0b923 100755
--- a/test/ral/type/filesources.rb
+++ b/test/ral/type/filesources.rb
@@ -292,11 +292,9 @@ class TestFileSources < Test::Unit::TestCase
# Lastly, make sure we return an empty array when no sources are there
obj[:source] = [nosource, tempfile()]
- assert_nothing_raised do
+ assert_raise(Puppet::Error) do
result, sourced = obj.sourcerecurse(true)
end
- assert_equal([], sourced, "Did not get correct list of sourced objects")
- assert_equal([], result, "Sourcerecurse failed when all sources are missing")
end
def test_simplelocalsource
diff --git a/test/ral/type/mailalias.rb b/test/ral/type/mailalias.rb
index ff1dd562a..637022330 100755
--- a/test/ral/type/mailalias.rb
+++ b/test/ral/type/mailalias.rb
@@ -34,12 +34,11 @@ class TestMailAlias < Test::Unit::TestCase
# This isn't much of a test, but then, it's not much of a type.
def test_recipient_arrays
resource = @type.create(:name => "luke", :recipient => "yay", :target => tempfile)
- resource.provider.expects(:recipient).returns([:absent])
values = nil
assert_nothing_raised("Could not retrieve mailalias") do
values = resource.retrieve.inject({}) { |hash, a| hash[a[0].name] = a[1]; hash }
end
- assert_equal([:absent], values[:recipient])
+ assert_equal(:absent, values[:recipient])
resource.property(:recipient).expects(:set).with(%w{yay})
assert_nothing_raised("Could not sync mailalias") do
resource.property(:recipient).sync
diff --git a/test/ral/type/user.rb b/test/ral/type/user.rb
index 87d5b6075..4c8a9f9c3 100755
--- a/test/ral/type/user.rb
+++ b/test/ral/type/user.rb
@@ -164,56 +164,6 @@ class TestUser < Test::Unit::TestCase
assert_equal(old, user.provider.shell, "Shell was not reverted")
end
- def attrtest_gid(user)
- obj = nil
- old = user.provider.gid
- comp = mk_catalog("gidtest", user)
-
- user.retrieve
-
- user[:gid] = old
-
- trans = assert_events([], comp, "user")
-
- newgid = %w{nogroup nobody staff users daemon}.find { |gid|
- begin
- group = Etc.getgrnam(gid)
- rescue ArgumentError => detail
- next
- end
- old != group.gid and group.gid > 0
- }
-
- unless newgid
- $stderr.puts "Cannot find alternate group; skipping gid test"
- return
- end
-
- # first test by name
- assert_nothing_raised("Failed to specify group by name") {
- user[:gid] = newgid
- }
-
- trans = assert_events([:user_changed], comp, "user")
-
- # then by id
- newgid = Etc.getgrnam(newgid).gid
-
- assert_nothing_raised("Failed to specify group by id for %s" % newgid) {
- user[:gid] = newgid
- }
-
- user.retrieve
-
- assert_events([], comp, "user")
-
- assert_equal(newgid, user.provider.gid, "GID was not changed")
-
- assert_rollback_events(trans, [:user_changed], "user")
-
- assert_equal(old, user.provider.gid, "GID was not reverted")
- end
-
def attrtest_uid(user)
obj = nil
comp = mk_catalog("uidtest", user)
diff --git a/test/util/log.rb b/test/util/log.rb
index 523652f37..8c7703cb9 100755
--- a/test/util/log.rb
+++ b/test/util/log.rb
@@ -114,44 +114,6 @@ class TestLog < Test::Unit::TestCase
assert(FileTest.file?(file))
end
- def test_logtags
- path = tempfile
- File.open(path, "w") { |f| f.puts "yayness" }
-
- file = Puppet.type(:file).create(
- :path => path,
- :check => [:owner, :group, :mode, :checksum],
- :ensure => :file
- )
- file.tags = %w{this is a test}
-
- property = file.property(:ensure)
- assert(property, "Did not get property")
- log = nil
- assert_nothing_raised {
- log = Puppet::Util::Log.new(
- :level => :info,
- :source => property,
- :message => "A test message"
- )
- }
-
- # Now yaml and de-yaml it, and test again
- yamllog = YAML.load(YAML.dump(log))
-
- {:log => log, :yaml => yamllog}.each do |type, msg|
- assert(msg.tags, "Got no tags")
-
- msg.tags.each do |tag|
- assert(msg.tagged?(tag), "Was not tagged with %s" % tag)
- end
-
- assert_equal(msg.tags, property.tags, "Tags were not equal")
- assert_equal(msg.source, property.path, "Source was not set correctly")
- end
-
- end
-
# Verify that we can pass strings that match printf args
def test_percentlogs
Puppet::Util::Log.newdestination :syslog
@@ -182,27 +144,6 @@ class TestLog < Test::Unit::TestCase
assert_instance_of(String, msg.source)
end
- # Verify that loglevel behaves as one expects
- def test_loglevel
- path = tempfile()
- file = Puppet.type(:file).create(
- :path => path,
- :ensure => "file"
- )
-
- assert_nothing_raised {
- assert_equal(:notice, file[:loglevel])
- }
-
- assert_nothing_raised {
- file[:loglevel] = "warning"
- }
-
- assert_nothing_raised {
- assert_equal(:warning, file[:loglevel])
- }
- end
-
def test_destination_matching
dest = nil
assert_nothing_raised {
diff --git a/test/util/posixtest.rb b/test/util/posixtest.rb
deleted file mode 100755
index f64a95d18..000000000
--- a/test/util/posixtest.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/env ruby
-#
-# Created by Luke Kanies on 2006-11-07.
-# Copyright (c) 2006. All rights reserved.
-
-require File.dirname(__FILE__) + '/../lib/puppettest'
-
-require 'puppettest'
-require 'puppet/util/posix'
-
-class TestPosixUtil < Test::Unit::TestCase
- include PuppetTest
- include Puppet::Util::POSIX
-
- def mk_posix_resource(type, obj)
- field = idfield(type)
- res = Puppet::Type.type(type).create(
- :name => obj.name,
- field => obj.send(field)
- )
- res.setdefaults
- res
- end
-
- def test_get_posix_field
- {:group => nonrootgroup, :passwd => nonrootuser}.each do |space, obj|
- id = Puppet::Util.idfield(space)
- [obj.name, obj.send(id)].each do |test|
- value = nil
- assert_nothing_raised do
- value = get_posix_field(space, :name, test)
- end
- assert_equal(obj.name, value, "did not get correct value from get_posix_field (known to be broken on some platforms)")
- end
- end
- end
-
- def test_search_posix_field
- {:group => nonrootgroup, :passwd => nonrootuser}.each do |space, obj|
- id = Puppet::Util.idfield(space)
- [obj.name, obj.send(id)].each do |test|
- value = nil
- assert_nothing_raised do
- value = search_posix_field(space, :name, test)
- end
- assert_equal(obj.name, value, "did not get correct value from search_posix_field")
- end
- end
- end
-
- def test_get_provider_value
- user = nonrootuser
- obj = mk_posix_resource(:user, user)
-
- assert_nothing_raised do
- assert_equal(user.uid, get_provider_value(:user, :uid, user.uid))
- assert_equal(user.name, get_provider_value(:user, :name, user.name))
- end
- end
-
- def test_gid_and_uid
- {:user => nonrootuser, :group => nonrootgroup}.each do |type, obj|
- method = idfield(type)
- # First make sure we get it back with both name and id with no object
- [obj.name, obj.send(method)].each do |value|
- assert_equal(obj.send(method), send(method, value))
- end
-
- # Now make a Puppet resource and make sure we get it from that.
- resource = mk_posix_resource(type, obj)
-
- [obj.name, obj.send(method)].each do |value|
- assert_equal(obj.send(method), send(method, value))
- end
- end
- end
-
- def test_util_methods
- assert(Puppet::Util.respond_to?(:uid), "util does not have methods")
- end
-
- # First verify we can convert a known user
- def test_gidbyname
- %x{groups}.split(" ").each { |group|
- gid = nil
- assert_nothing_raised {
- gid = Puppet::Util.gid(group)
- }
-
- assert(gid, "Could not retrieve gid for %s" % group)
- }
- end
-
- # Then verify we can retrieve a known group by gid
- def test_gidbyid
- %x{groups}.split(" ").each { |group|
- obj = Puppet.type(:group).create(
- :name => group,
- :check => [:gid]
- )
- obj.setdefaults
- current = obj.retrieve
- id = nil
- current.find { |prop, value| id = value if prop.name == :gid }
- gid = nil
- assert_nothing_raised {
- gid = Puppet::Util.gid(id)
- }
-
- assert(gid, "Could not retrieve gid for %s" % group)
- assert_equal(id, gid, "Got mismatched ids")
- }
- end
-
- # Finally, verify that we can find groups by id even if we don't
- # know them
- def test_gidbyunknownid
- gid = nil
- group = Puppet::Util::SUIDManager.gid
- assert_nothing_raised {
- gid = Puppet::Util.gid(group)
- }
-
- assert(gid, "Could not retrieve gid for %s" % group)
- assert_equal(group, gid, "Got mismatched ids")
- end
-
- def user
- require 'etc'
- unless defined? @user
- obj = Etc.getpwuid(Puppet::Util::SUIDManager.uid)
- @user = obj.name
- end
- return @user
- end
-
- # And do it all over again for users
- # First verify we can convert a known user
- def test_uidbyname
- user = user()
- uid = nil
- assert_nothing_raised {
- uid = Puppet::Util.uid(user)
- }
-
- assert(uid, "Could not retrieve uid for %s" % user)
- assert_equal(Puppet::Util::SUIDManager.uid, uid, "UIDs did not match")
- end
-
- # Then verify we can retrieve a known user by uid
- def test_uidbyid
- user = user()
- obj = Puppet.type(:user).create(
- :name => user,
- :check => [:uid]
- )
- obj.setdefaults
- obj.retrieve
- id = obj.provider.uid
- uid = nil
- assert_nothing_raised {
- uid = Puppet::Util.uid(id)
- }
-
- assert(uid, "Could not retrieve uid for %s" % user)
- assert_equal(id, uid, "Got mismatched ids")
- end
-
- # Finally, verify that we can find users by id even if we don't
- # know them
- def test_uidbyunknownid
- uid = nil
- user = Puppet::Util::SUIDManager.uid
- assert_nothing_raised {
- uid = Puppet::Util.uid(user)
- }
-
- assert(uid, "Could not retrieve uid for %s" % user)
- assert_equal(user, uid, "Got mismatched ids")
- end
-end
-