summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-09-23 22:31:55 -0500
committerLuke Kanies <luke@madstop.com>2008-09-23 22:31:55 -0500
commit4aeabbbb2163684ff7064198c653cd60d46e5717 (patch)
tree7c3593bde6b7f28f3e20444a576eb37338cced14
parent5b9dd01326a61b9ae89ae978e29a8170f76deb5e (diff)
parent8d5ded09b9c9c944695c015e6e95b10ccebd6fb5 (diff)
downloadpuppet-4aeabbbb2163684ff7064198c653cd60d46e5717.tar.gz
puppet-4aeabbbb2163684ff7064198c653cd60d46e5717.tar.xz
puppet-4aeabbbb2163684ff7064198c653cd60d46e5717.zip
Merge branch '0.24.x'
Conflicts: lib/puppet/metatype/container.rb lib/puppet/metatype/instances.rb lib/puppet/metatype/metaparams.rb lib/puppet/metatype/relationships.rb lib/puppet/metatype/schedules.rb
-rw-r--r--CHANGELOG43
-rwxr-xr-xbin/puppetrun2
-rwxr-xr-xconf/osx/createpackage.sh2
-rw-r--r--conf/redhat/puppet.spec12
-rwxr-xr-xinstall.rb12
-rw-r--r--lib/puppet/defaults.rb3
-rw-r--r--lib/puppet/metatype/attributes.rb685
-rw-r--r--lib/puppet/metatype/closure.rb49
-rw-r--r--lib/puppet/metatype/container.rb2
-rw-r--r--lib/puppet/metatype/evaluation.rb163
-rw-r--r--lib/puppet/metatype/providers.rb247
-rw-r--r--lib/puppet/metatype/tags.rb38
-rw-r--r--lib/puppet/module.rb40
-rw-r--r--lib/puppet/network/client/master.rb16
-rw-r--r--lib/puppet/network/handler/master.rb2
-rw-r--r--lib/puppet/node.rb6
-rw-r--r--lib/puppet/parameter.rb29
-rw-r--r--lib/puppet/parser/ast/vardef.rb4
-rw-r--r--lib/puppet/parser/grammar.ra8
-rw-r--r--lib/puppet/parser/lexer.rb1
-rw-r--r--lib/puppet/parser/parser.rb1437
-rw-r--r--lib/puppet/parser/scope.rb26
-rw-r--r--lib/puppet/property.rb8
-rw-r--r--lib/puppet/provider/package/appdmg.rb2
-rw-r--r--lib/puppet/provider/package/pkgdmg.rb2
-rw-r--r--lib/puppet/provider/service/daemontools.rb154
-rw-r--r--lib/puppet/provider/service/runit.rb93
-rw-r--r--lib/puppet/provider/user/hpux.rb30
-rw-r--r--lib/puppet/type.rb2097
-rw-r--r--lib/puppet/type/file.rb9
-rw-r--r--lib/puppet/type/package.rb4
-rwxr-xr-xlib/puppet/type/user.rb8
-rw-r--r--lib/puppet/util.rb12
-rw-r--r--lib/puppet/util/ldap/connection.rb12
-rw-r--r--lib/puppet/util/plist.rb23
-rw-r--r--lib/puppet/util/plist/generator.rb225
-rw-r--r--lib/puppet/util/plist/parser.rb226
-rwxr-xr-xspec/unit/module.rb27
-rwxr-xr-xspec/unit/network/client/master.rb42
-rwxr-xr-xspec/unit/parameter.rb24
-rwxr-xr-xspec/unit/parser/ast/vardef.rb47
-rwxr-xr-xspec/unit/parser/lexer.rb3
-rwxr-xr-xspec/unit/parser/parser.rb34
-rwxr-xr-xspec/unit/parser/scope.rb37
-rwxr-xr-xspec/unit/property.rb35
-rw-r--r--spec/unit/provider/service/daemontools.rb124
-rw-r--r--spec/unit/provider/service/runit.rb117
-rwxr-xr-xspec/unit/provider/user/hpux.rb25
-rwxr-xr-xspec/unit/type/file.rb6
-rwxr-xr-xspec/unit/type/noop_metaparam.rb2
-rwxr-xr-xspec/unit/util/ldap/connection.rb13
-rw-r--r--test/data/snippets/append.pp11
-rwxr-xr-xtest/language/functions.rb10
53 files changed, 3825 insertions, 2464 deletions
diff --git a/CHANGELOG b/CHANGELOG
index eab387b20..2c8ef2fb2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,49 @@
set file paths to 'false' to disable the CRL.
0.24.x
+ Fixed #1595 - Internally, Property#retrieve is no longer called
+ when no 'should' value is available for a resource.
+
+ Fixed #1584 - Added support for appended variables
+
+ Fixed #1554 - Added support for multiple template directories
+
+ Fixed #1500 - puppetrun not working
+
+ Fixed #1579 and #1580 - errors in the Puppet RPM spec file
+
+ Fixed #1572 -- file purging now fails if remote sources do not exist.
+
+ Fixed #1521 -- ldap user and password are now used with the default connection.
+
+ Fixed issues with file descriptors leaking into subprocesses
+
+ Fixed #1568 - createpackage.sh
+
+ Fixed #1571 - Puppet::Util::binary returns incorrect results
+
+ Fixed #1553 - Puppet and Facter cannot both install the plist module into two different locations
+
+ Adjusted hpuxuseradd user provider to confine to HP-UX and fixed HP-UX user provider path regression
+
+ Fixed debug messages in package type - thanks to Todd Zullinger for this fix
+
+ Fixed #1566 - changed password property of the user type
+
+ Fixed debug messages in package type
+
+ Updated Red Hat spec file
+
+ Fixes #1455 - Adds HP-UX support for user type
+
+ Fixes #1551 puppetmaster.freshness xmlrpc call returns incorrect type
+
+ Fixes #1554 - Fix exception for undefined hostname
+
+ Fixed #1533 - changed permissions for man directory
+
+ Added daemontools and runit providers for service type
+
Added simple rake task for running unit tests
Added spec Rake task
diff --git a/bin/puppetrun b/bin/puppetrun
index f33c7f8a1..28f72d9c3 100755
--- a/bin/puppetrun
+++ b/bin/puppetrun
@@ -245,7 +245,7 @@ end
# Now parse the config
Puppet.parse_config
-if Puppet[:node_terminus] = "ldap"
+if Puppet[:node_terminus] == "ldap" and (options[:all] or classes)
if options[:all]
hosts = Puppet::Node.search("whatever").collect { |node| node.name }
puts "all: %s" % hosts.join(", ")
diff --git a/conf/osx/createpackage.sh b/conf/osx/createpackage.sh
index 3ac4d09de..32cbebfc5 100755
--- a/conf/osx/createpackage.sh
+++ b/conf/osx/createpackage.sh
@@ -49,7 +49,7 @@ function find_puppet_root() {
function install_puppet() {
echo "Installing Puppet to ${pkgroot}"
- "${installer}" --destdir="${pkgroot}" --bindir="${BINDIR}" --sitelibdir="${SITELIBDIR}" &> /dev/null
+ "${installer}" --destdir="${pkgroot}" --bindir="${BINDIR}" --sitelibdir="${SITELIBDIR}"
chown -R root:admin "${pkgroot}"
}
diff --git a/conf/redhat/puppet.spec b/conf/redhat/puppet.spec
index 92a42ce7b..b5090ed38 100644
--- a/conf/redhat/puppet.spec
+++ b/conf/redhat/puppet.spec
@@ -2,7 +2,7 @@
%define pbuild %{_builddir}/%{name}-%{version}
%define confdir conf/redhat
-%define has_ruby_abi 0%{?fedora:%fedora} >= 5 || 0%{?rhel:%rhel} >= 5
+%define has_ruby_abi 0%{?fedora:%fedora} >= 5 || 0%{?rhel:%rhel} >= 5 || 0%{?centos:%centos} >= 5
%define has_ruby_noarch %has_ruby_abi
Summary: A network tool for managing many disparate systems
@@ -51,8 +51,8 @@ done
# Fix some rpmlint complaints
for f in mac_dscl.pp mac_dscl_revert.pp \
mac_netinfo.pp mac_pkgdmg.pp ; do
- sed -i -e'1d' examples/code/$f
- chmod a-x examples/code/$f
+ sed -i -e'1d' examples/$f
+ chmod a-x examples/$f
done
find examples/ -type f -empty | xargs rm
@@ -65,6 +65,7 @@ install -d -m0755 %{buildroot}%{_bindir}
install -d -m0755 %{buildroot}%{ruby_sitelibdir}
install -d -m0755 %{buildroot}%{_sysconfdir}/puppet/manifests
install -d -m0755 %{buildroot}%{_docdir}/%{name}-%{version}
+install -d -m0755 %{buildroot}%{_mandir}/man8
install -d -m0755 %{buildroot}%{_localstatedir}/lib/puppet
install -d -m0755 %{buildroot}%{_localstatedir}/run/puppet
install -d -m0755 %{buildroot}%{_localstatedir}/log/puppet
@@ -84,6 +85,7 @@ install -Dp -m0755 %{confdir}/server.init %{buildroot}%{_initrddir}/puppetmaster
install -Dp -m0644 %{confdir}/fileserver.conf %{buildroot}%{_sysconfdir}/puppet/fileserver.conf
install -Dp -m0644 %{confdir}/puppet.conf %{buildroot}%{_sysconfdir}/puppet/puppet.conf
install -Dp -m0644 %{confdir}/logrotate %{buildroot}%{_sysconfdir}/logrotate.d/puppet
+install -Dp -m0644 man/man8/* %{buildroot}%{_mandir}/man8
# We need something for these ghosted files, otherwise rpmbuild
# will complain loudly. They won't be included in the binary packages
touch %{buildroot}%{_sysconfdir}/puppet/puppetmasterd.conf
@@ -128,6 +130,10 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf
%ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetca.conf
%ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetmasterd.conf
%{_sbindir}/puppetca
+%doc %{_mandir}/man8/filebucket.8.gz
+%doc %{_mandir}/man8/puppetca.8.gz
+%doc %{_mandir}/man8/puppetmasterd.8.gz
+%doc %{_mandir}/man8/puppetrun.8.gz
%pre
/usr/sbin/groupadd -r puppet 2>/dev/null || :
diff --git a/install.rb b/install.rb
index a2cbdb429..c99d7dacd 100755
--- a/install.rb
+++ b/install.rb
@@ -60,6 +60,7 @@ rescue
end
PREREQS = %w{openssl facter xmlrpc/client xmlrpc/server cgi}
+MIN_FACTER_VERSION = 1.5
InstallOptions = OpenStruct.new
@@ -102,7 +103,7 @@ def do_man(man, strip = 'man/')
omf = File.join(InstallOptions.man_dir, mf.gsub(/#{strip}/, ''))
om = File.dirname(omf)
File.makedirs(om, true)
- File.chmod(0644, om)
+ File.chmod(0755, om)
File.install(mf, omf, 0644, true)
gzip = %x{which gzip}
gzip.chomp!
@@ -115,6 +116,15 @@ def check_prereqs
PREREQS.each { |pre|
begin
require pre
+ if pre == "facter"
+ # to_f isn't quite exact for strings like "1.5.1" but is good
+ # enough for this purpose.
+ facter_version = Facter.version.to_f
+ if facter_version < MIN_FACTER_VERSION
+ puts "Facter version: %s; minimum required: %s; cannot install" % [facter_version, MIN_FACTER_VERSION]
+ exit -1
+ end
+ end
rescue LoadError
puts "Could not load %s; cannot install" % pre
exit -1
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 7c57dcd6d..d0dcb1c51 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -675,7 +675,8 @@ module Puppet
setdefaults(:parser,
:lexical => [false, "Whether to use lexical scoping (vs. dynamic)."],
:templatedir => ["$vardir/templates",
- "Where Puppet looks for template files."
+ "Where Puppet looks for template files. Can be a list of colon-seperated
+ directories."
]
)
diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb
deleted file mode 100644
index 3f48f22ff..000000000
--- a/lib/puppet/metatype/attributes.rb
+++ /dev/null
@@ -1,685 +0,0 @@
-require 'puppet'
-require 'puppet/type'
-
-class Puppet::Type
- class << self
- include Puppet::Util::ClassGen
- include Puppet::Util::Warnings
- attr_reader :properties
- end
-
- def self.states
- warnonce "The states method is deprecated; use properties"
- properties()
- end
-
- # All parameters, in the appropriate order. The namevar comes first,
- # then the properties, then the params and metaparams in the order they
- # were specified in the files.
- def self.allattrs
- # now get all of the arguments, in a specific order
- # Cache this, since it gets called so many times
- namevar = self.namevar
-
- order = [namevar]
- if self.parameters.include?(:provider)
- order << :provider
- end
- order << [self.properties.collect { |property| property.name },
- self.parameters - [:provider],
- self.metaparams].flatten.reject { |param|
- # we don't want our namevar in there multiple times
- param == namevar
- }
-
- order.flatten!
-
- return order
- end
-
- # Retrieve an attribute alias, if there is one.
- def self.attr_alias(param)
- @attr_aliases[symbolize(param)]
- end
-
- # Create an alias to an existing attribute. This will cause the aliased
- # attribute to be valid when setting and retrieving values on the instance.
- def self.set_attr_alias(hash)
- hash.each do |new, old|
- @attr_aliases[symbolize(new)] = symbolize(old)
- end
- end
-
- # Find the class associated with any given attribute.
- def self.attrclass(name)
- @attrclasses ||= {}
-
- # We cache the value, since this method gets called such a huge number
- # of times (as in, hundreds of thousands in a given run).
- unless @attrclasses.include?(name)
- @attrclasses[name] = case self.attrtype(name)
- when :property: @validproperties[name]
- when :meta: @@metaparamhash[name]
- when :param: @paramhash[name]
- end
- end
- @attrclasses[name]
- end
-
- # What type of parameter are we dealing with? Cache the results, because
- # this method gets called so many times.
- def self.attrtype(attr)
- @attrtypes ||= {}
- unless @attrtypes.include?(attr)
- @attrtypes[attr] = case
- when @validproperties.include?(attr): :property
- when @paramhash.include?(attr): :param
- when @@metaparamhash.include?(attr): :meta
- else
- raise Puppet::DevError,
- "Invalid attribute '%s' for class '%s'" %
- [attr, self.name]
- end
- end
-
- @attrtypes[attr]
- end
-
- # Copy an existing class parameter. This allows other types to avoid
- # duplicating a parameter definition, and is mostly used by subclasses
- # of the File class.
- def self.copyparam(klass, name)
- param = klass.attrclass(name)
-
- unless param
- raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
- end
- @parameters << param
- @parameters.each { |p| @paramhash[name] = p }
-
- if param.isnamevar?
- @namevar = param.name
- end
- end
-
- # A similar function but one that yields the class and type.
- # This is mainly so that setdefaults doesn't call quite so many functions.
- def self.eachattr(*ary)
- if ary.empty?
- ary = nil
- end
-
- # We have to do this in a specific order, so that defaults are
- # created in that order (e.g., providers should be set up before
- # anything else).
- allattrs.each do |name|
- next unless ary.nil? or ary.include?(name)
- if obj = @properties.find { |p| p.name == name }
- yield obj, :property
- elsif obj = @parameters.find { |p| p.name == name }
- yield obj, :param
- elsif obj = @@metaparams.find { |p| p.name == name }
- yield obj, :meta
- else
- raise Puppet::DevError, "Could not find parameter %s" % name
- end
- end
- end
-
- def self.eachmetaparam
- @@metaparams.each { |p| yield p.name }
- end
-
- # Create the 'ensure' class. This is a separate method so other types
- # can easily call it and create their own 'ensure' values.
- def self.ensurable(&block)
- if block_given?
- self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block)
- else
- self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do
- self.defaultvalues
- end
- end
- end
-
- # Should we add the 'ensure' property to this class?
- def self.ensurable?
- # If the class has all three of these methods defined, then it's
- # ensurable.
- ens = [:exists?, :create, :destroy].inject { |set, method|
- set &&= self.public_method_defined?(method)
- }
-
- return ens
- end
-
- # Deal with any options passed into parameters.
- def self.handle_param_options(name, options)
- # If it's a boolean parameter, create a method to test the value easily
- if options[:boolean]
- define_method(name.to_s + "?") do
- val = self[name]
- if val == :true or val == true
- return true
- end
- end
- end
-
- # If this param handles relationships, store that information
- end
-
- # Is the parameter in question a meta-parameter?
- def self.metaparam?(param)
- @@metaparamhash.include?(symbolize(param))
- end
-
- # Find the metaparameter class associated with a given metaparameter name.
- def self.metaparamclass(name)
- @@metaparamhash[symbolize(name)]
- end
-
- def self.metaparams
- @@metaparams.collect { |param| param.name }
- end
-
- def self.metaparamdoc(metaparam)
- @@metaparamhash[metaparam].doc
- end
-
- # Create a new metaparam. Requires a block and a name, stores it in the
- # @parameters array, and does some basic checking on it.
- def self.newmetaparam(name, options = {}, &block)
- @@metaparams ||= []
- @@metaparamhash ||= {}
- name = symbolize(name)
-
- param = genclass(name,
- :parent => options[:parent] || Puppet::Parameter,
- :prefix => "MetaParam",
- :hash => @@metaparamhash,
- :array => @@metaparams,
- :attributes => options[:attributes],
- &block
- )
-
- # Grr.
- if options[:required_features]
- param.required_features = options[:required_features]
- end
-
- handle_param_options(name, options)
-
- param.metaparam = true
-
- return param
- end
-
- # Find the namevar
- def self.namevar
- unless defined? @namevar
- params = @parameters.find_all { |param|
- param.isnamevar? or param.name == :name
- }
-
- if params.length > 1
- raise Puppet::DevError, "Found multiple namevars for %s" % self.name
- elsif params.length == 1
- @namevar = params[0].name
- else
- raise Puppet::DevError, "No namevar for %s" % self.name
- end
- end
- @namevar
- end
-
- # Create a new parameter. Requires a block and a name, stores it in the
- # @parameters array, and does some basic checking on it.
- def self.newparam(name, options = {}, &block)
- options[:attributes] ||= {}
- param = genclass(name,
- :parent => options[:parent] || Puppet::Parameter,
- :attributes => options[:attributes],
- :block => block,
- :prefix => "Parameter",
- :array => @parameters,
- :hash => @paramhash
- )
-
- handle_param_options(name, options)
-
- # Grr.
- if options[:required_features]
- param.required_features = options[:required_features]
- end
-
- param.isnamevar if options[:namevar]
-
- # These might be enabled later.
-# define_method(name) do
-# @parameters[name].value
-# end
-#
-# define_method(name.to_s + "=") do |value|
-# newparam(param, value)
-# end
-
- if param.isnamevar?
- @namevar = param.name
- end
-
- return param
- end
-
- def self.newstate(name, options = {}, &block)
- Puppet.warning "newstate() has been deprecrated; use newproperty(%s)" %
- name
- newproperty(name, options, &block)
- end
-
- # Create a new property. The first parameter must be the name of the property;
- # this is how users will refer to the property when creating new instances.
- # The second parameter is a hash of options; the options are:
- # * <tt>:parent</tt>: The parent class for the property. Defaults to Puppet::Property.
- # * <tt>:retrieve</tt>: The method to call on the provider or @parent object (if
- # the provider is not set) to retrieve the current value.
- def self.newproperty(name, options = {}, &block)
- name = symbolize(name)
-
- # This is here for types that might still have the old method of defining
- # a parent class.
- unless options.is_a? Hash
- raise Puppet::DevError,
- "Options must be a hash, not %s" % options.inspect
- end
-
- if @validproperties.include?(name)
- raise Puppet::DevError, "Class %s already has a property named %s" %
- [self.name, name]
- end
-
- if parent = options[:parent]
- options.delete(:parent)
- else
- parent = Puppet::Property
- end
-
- # We have to create our own, new block here because we want to define
- # an initial :retrieve method, if told to, and then eval the passed
- # block if available.
- prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do
- # If they've passed a retrieve method, then override the retrieve
- # method on the class.
- if options[:retrieve]
- define_method(:retrieve) do
- provider.send(options[:retrieve])
- end
- end
-
- if block
- class_eval(&block)
- end
- end
-
- # If it's the 'ensure' property, always put it first.
- if name == :ensure
- @properties.unshift prop
- else
- @properties << prop
- end
-
-# define_method(name) do
-# @parameters[name].should
-# end
-#
-# define_method(name.to_s + "=") do |value|
-# newproperty(name, :should => value)
-# end
-
- return prop
- end
-
- def self.paramdoc(param)
- @paramhash[param].doc
- end
-
- # Return the parameter names
- def self.parameters
- return [] unless defined? @parameters
- @parameters.collect { |klass| klass.name }
- end
-
- # Find the parameter class associated with a given parameter name.
- def self.paramclass(name)
- @paramhash[name]
- end
-
- # Return the property class associated with a name
- def self.propertybyname(name)
- @validproperties[name]
- end
-
- def self.validattr?(name)
- name = symbolize(name)
- return true if name == :name
- @validattrs ||= {}
-
- unless @validattrs.include?(name)
- if self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)
- @validattrs[name] = true
- else
- @validattrs[name] = false
- end
- end
-
- @validattrs[name]
- end
-
- # does the name reflect a valid property?
- def self.validproperty?(name)
- name = symbolize(name)
- if @validproperties.include?(name)
- return @validproperties[name]
- else
- return false
- end
- end
-
- # Return the list of validproperties
- def self.validproperties
- return {} unless defined? @parameters
-
- return @validproperties.keys
- end
-
- # does the name reflect a valid parameter?
- def self.validparameter?(name)
- unless defined? @parameters
- raise Puppet::DevError, "Class %s has not defined parameters" % self
- end
- if @paramhash.include?(name) or @@metaparamhash.include?(name)
- return true
- else
- return false
- end
- end
-
- # fix any namevar => param translations
- def argclean(oldhash)
- # This duplication is here because it might be a transobject.
- hash = oldhash.dup.to_hash
-
- if hash.include?(:resource)
- hash.delete(:resource)
- end
- namevar = self.class.namevar
-
- # Do a simple translation for those cases where they've passed :name
- # but that's not our namevar
- if hash.include? :name and namevar != :name
- if hash.include? namevar
- raise ArgumentError, "Cannot provide both name and %s" % namevar
- end
- hash[namevar] = hash[:name]
- hash.delete(:name)
- end
-
- # Make sure we have a name, one way or another
- unless hash.include? namevar
- if defined? @title and @title
- hash[namevar] = @title
- else
- raise Puppet::Error, "Was not passed a namevar or title"
- end
- end
-
- return hash
- end
-
- # Return either the attribute alias or the attribute.
- def attr_alias(name)
- name = symbolize(name)
- if synonym = self.class.attr_alias(name)
- return synonym
- else
- return name
- end
- end
-
- # Are we deleting this resource?
- def deleting?
- obj = @parameters[:ensure] and obj.should == :absent
- end
-
- # Create a new property if it is valid but doesn't exist
- # Returns: true if a new parameter was added, false otherwise
- def add_property_parameter(prop_name)
- if self.class.validproperty?(prop_name) && !@parameters[prop_name]
- self.newattr(prop_name)
- return true
- end
- return false
- end
-
- # abstract accessing parameters and properties, and normalize
- # access to always be symbols, not strings
- # This returns a value, not an object. It returns the 'is'
- # value, but you can also specifically return 'is' and 'should'
- # values using 'object.is(:property)' or 'object.should(:property)'.
- def [](name)
- name = attr_alias(name)
-
- unless self.class.validattr?(name)
- raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
- end
-
- if name == :name
- name = self.class.namevar
- end
-
- if obj = @parameters[name]
- # Note that if this is a property, then the value is the "should" value,
- # not the current value.
- obj.value
- else
- return nil
- end
- end
-
- # Abstract setting parameters and properties, and normalize
- # access to always be symbols, not strings. This sets the 'should'
- # value on properties, and otherwise just sets the appropriate parameter.
- def []=(name,value)
- name = attr_alias(name)
-
- unless self.class.validattr?(name)
- raise TypeError.new("Invalid parameter %s" % [name])
- end
-
- if name == :name
- name = self.class.namevar
- end
- if value.nil?
- raise Puppet::Error.new("Got nil value for %s" % name)
- end
-
- if obj = @parameters[name]
- obj.value = value
- return nil
- else
- self.newattr(name, :value => value)
- end
-
- nil
- end
-
- # remove a property from the object; useful in testing or in cleanup
- # when an error has been encountered
- def delete(attr)
- attr = symbolize(attr)
- if @parameters.has_key?(attr)
- @parameters.delete(attr)
- else
- raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
- end
- end
-
- # iterate across the existing properties
- def eachproperty
- # properties() is a private method
- properties().each { |property|
- yield property
- }
- end
-
- # retrieve the 'should' value for a specified property
- def should(name)
- name = attr_alias(name)
- if prop = @parameters[name] and prop.is_a?(Puppet::Property)
- return prop.should
- else
- return nil
- end
- end
-
- # Create the actual attribute instance. Requires either the attribute
- # name or class as the first argument, then an optional hash of
- # attributes to set during initialization.
- def newattr(name, options = {})
- if name.is_a?(Class)
- klass = name
- name = klass.name
- end
-
- unless klass = self.class.attrclass(name)
- raise Puppet::Error, "Resource type %s does not support parameter %s" % [self.class.name, name]
- end
-
- if @parameters.include?(name)
- raise Puppet::Error, "Parameter '%s' is already defined in %s" %
- [name, self.ref]
- end
-
- if provider and ! provider.class.supports_parameter?(klass)
- missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) }
- info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name]
- return nil
- end
-
- # Add resource information at creation time, so it's available
- # during validation.
- options[:resource] = self
- begin
- # make sure the parameter doesn't have any errors
- return @parameters[name] = klass.new(options)
- rescue => detail
- error = Puppet::Error.new("Parameter %s failed: %s" %
- [name, detail])
- error.set_backtrace(detail.backtrace)
- raise error
- end
- end
-
- # return the value of a parameter
- def parameter(name)
- unless name.is_a? Symbol
- name = name.intern
- end
- return @parameters[name].value
- end
-
- # Is the named property defined?
- def propertydefined?(name)
- unless name.is_a? Symbol
- name = name.intern
- end
- return @parameters.include?(name)
- end
-
- # return an actual type by name; to return the value, use 'inst[name]'
- # FIXME this method should go away
- def property(name)
- if obj = @parameters[symbolize(name)] and obj.is_a?(Puppet::Property)
- return obj
- else
- return nil
- end
- end
-
-# def set(name, value)
-# send(name.to_s + "=", value)
-# end
-#
-# def get(name)
-# send(name)
-# end
-
- # For any parameters or properties that have defaults and have not yet been
- # set, set them now. This method can be handed a list of attributes,
- # and if so it will only set defaults for those attributes.
- def setdefaults(*ary)
- #self.class.eachattr(*ary) { |klass, type|
- self.class.eachattr(*ary) { |klass, type|
- # not many attributes will have defaults defined, so we short-circuit
- # those away
- next unless klass.method_defined?(:default)
- next if @parameters[klass.name]
-
- next unless obj = self.newattr(klass)
-
- # We have to check for nil values, not "truth", so we allow defaults
- # to false.
- value = obj.default and ! value.nil?
- if ! value.nil?
- obj.value = value
- else
- @parameters.delete(obj.name)
- end
- }
- end
-
- # Convert our object to a hash. This just includes properties.
- def to_hash
- rethash = {}
-
- @parameters.each do |name, obj|
- rethash[name] = obj.value
- end
-
- rethash
- end
-
- # Return a specific value for an attribute.
- def value(name)
- name = attr_alias(name)
-
- if obj = @parameters[name] and obj.respond_to?(:value)
- return obj.value
- else
- return nil
- end
- end
-
- # Meta-parameter methods: These methods deal with the results
- # of specifying metaparameters
-
- private
-
- # Return all of the property objects, in the order specified in the
- # class.
- def properties
- #debug "%s has %s properties" % [self,@parameters.length]
- props = self.class.properties.collect { |prop|
- @parameters[prop.name]
- }.find_all { |p|
- ! p.nil?
- }.each do |prop|
- unless prop.is_a?(Puppet::Property)
- raise Puppet::DevError, "got a non-property %s(%s)" %
- [prop.class, prop.class.name]
- end
- end
-
- props
- end
-end
-
diff --git a/lib/puppet/metatype/closure.rb b/lib/puppet/metatype/closure.rb
deleted file mode 100644
index 673a2359d..000000000
--- a/lib/puppet/metatype/closure.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-class Puppet::Type
- attr_writer :implicit
-
- # Is this type's name isomorphic with the object? That is, if the
- # name conflicts, does it necessarily mean that the objects conflict?
- # Defaults to true.
- def self.isomorphic?
- if defined? @isomorphic
- return @isomorphic
- else
- return true
- end
- end
-
- def implicit?
- if defined? @implicit and @implicit
- return true
- else
- return false
- end
- end
-
- def isomorphic?
- self.class.isomorphic?
- end
-
- # is the instance a managed instance? A 'yes' here means that
- # the instance was created from the language, vs. being created
- # in order resolve other questions, such as finding a package
- # in a list
- def managed?
- # Once an object is managed, it always stays managed; but an object
- # that is listed as unmanaged might become managed later in the process,
- # so we have to check that every time
- if defined? @managed and @managed
- return @managed
- else
- @managed = false
- properties.each { |property|
- s = property.should
- if s and ! property.class.unmanaged
- @managed = true
- break
- end
- }
- return @managed
- end
- end
-end
diff --git a/lib/puppet/metatype/container.rb b/lib/puppet/metatype/container.rb
index dbc8a3dee..0e06e71d2 100644
--- a/lib/puppet/metatype/container.rb
+++ b/lib/puppet/metatype/container.rb
@@ -1,7 +1,5 @@
class Puppet::Type
- # this is a retarded hack method to get around the difference between
- # component children and file children
def self.depthfirst?
if defined? @depthfirst
return @depthfirst
diff --git a/lib/puppet/metatype/evaluation.rb b/lib/puppet/metatype/evaluation.rb
deleted file mode 100644
index 18bbb812f..000000000
--- a/lib/puppet/metatype/evaluation.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-class Puppet::Type
- # This method is responsible for collecting property changes we always
- # descend into the children before we evaluate our current properties.
- # This returns any changes resulting from testing, thus 'collect' rather
- # than 'each'.
- def evaluate
- if self.provider.is_a?(Puppet::Provider)
- unless provider.class.suitable?
- raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
- end
- end
- #Puppet.err "Evaluating %s" % self.path.join(":")
- unless defined? @evalcount
- self.err "No evalcount defined on '%s' of type '%s'" %
- [self.title,self.class]
- @evalcount = 0
- end
- @evalcount += 1
-
- if p = self.provider and p.respond_to?(:prefetch)
- p.prefetch
- end
-
- # this only operates on properties, not properties + children
- # it's important that we call retrieve() on the type instance,
- # not directly on the property, because it allows the type to override
- # the method, like pfile does
- currentvalues = self.retrieve
-
- changes = propertychanges(currentvalues).flatten
-
- # now record how many changes we've resulted in
- if changes.length > 0
- self.debug "%s change(s)" %
- [changes.length]
- end
-
- # If we're in noop mode, we don't want to store the checked time,
- # because it will result in the resource not getting scheduled if
- # someone were to apply the catalog in non-noop mode.
- # We're going to go ahead and record that we checked if there were
- # no changes, since it's unlikely it will affect the scheduling.
- noop = noop?
- if ! noop or (noop && changes.length == 0)
- self.cache(:checked, Time.now)
- end
- return changes.flatten
- end
-
- # Flush the provider, if it supports it. This is called by the
- # transaction.
- def flush
- if self.provider and self.provider.respond_to?(:flush)
- self.provider.flush
- end
- end
-
- # if all contained objects are in sync, then we're in sync
- # FIXME I don't think this is used on the type instances any more,
- # it's really only used for testing
- def insync?(is)
- insync = true
-
- if property = @parameters[:ensure]
- unless is.include? property
- raise Puppet::DevError,
- "The is value is not in the is array for '%s'" %
- [property.name]
- end
- ensureis = is[property]
- if property.insync?(ensureis) and property.should == :absent
- return true
- end
- end
-
- properties.each { |property|
- unless is.include? property
- raise Puppet::DevError,
- "The is value is not in the is array for '%s'" %
- [property.name]
- end
-
- propis = is[property]
- unless property.insync?(propis)
- property.debug("Not in sync: %s vs %s" %
- [propis.inspect, property.should.inspect])
- insync = false
- #else
- # property.debug("In sync")
- end
- }
-
- #self.debug("%s sync status is %s" % [self,insync])
- return insync
- end
-
- # retrieve the current value of all contained properties
- def retrieve
- 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
- }
- end
-
- # Are we running in noop mode?
- def noop?
- if defined?(@noop)
- @noop
- else
- Puppet[:noop]
- end
- end
-
- def noop
- noop?
- end
-
- # Retrieve the changes associated with all of the properties.
- def propertychanges(currentvalues)
- # If we are changing the existence of the object, then none of
- # the other properties matter.
- changes = []
- ensureparam = @parameters[:ensure]
-
- # This allows resource types to have 'ensure' be a parameter, which allows them to
- # just pass the parameter on to other generated resources.
- ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
- if ensureparam && !currentvalues.include?(ensureparam)
- raise Puppet::DevError, "Parameter ensure defined but missing from current values"
- end
-
- if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
- changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
- # Else, if the 'ensure' property is correctly absent, then do
- # nothing
- elsif ensureparam and currentvalues[ensureparam] == :absent
- return []
- else
- changes = properties().find_all { |property|
- currentvalues[property] ||= :absent
- ! property.insync?(currentvalues[property])
- }.collect { |property|
- Puppet::Transaction::Change.new(property, currentvalues[property])
- }
- end
-
- if Puppet[:debug] and changes.length > 0
- self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
- end
-
- changes
- end
-end
-
diff --git a/lib/puppet/metatype/providers.rb b/lib/puppet/metatype/providers.rb
deleted file mode 100644
index 6308f7e54..000000000
--- a/lib/puppet/metatype/providers.rb
+++ /dev/null
@@ -1,247 +0,0 @@
-require 'puppet/provider'
-require 'puppet/util/provider_features'
-class Puppet::Type
- # Add the feature handling module.
- extend Puppet::Util::ProviderFeatures
-
- attr_reader :provider
-
- # the Type class attribute accessors
- class << self
- attr_accessor :providerloader
- attr_writer :defaultprovider
- end
-
- # Find the default provider.
- def self.defaultprovider
- unless defined? @defaultprovider and @defaultprovider
- suitable = suitableprovider()
-
- # Find which providers are a default for this system.
- defaults = suitable.find_all { |provider| provider.default? }
-
- # If we don't have any default we use suitable providers
- defaults = suitable if defaults.empty?
- max = defaults.collect { |provider| provider.defaultnum }.max
- defaults = defaults.find_all { |provider| provider.defaultnum == max }
-
- retval = nil
- if defaults.length > 1
- Puppet.warning(
- "Found multiple default providers for %s: %s; using %s" %
- [self.name, defaults.collect { |i| i.name.to_s }.join(", "),
- defaults[0].name]
- )
- retval = defaults.shift
- elsif defaults.length == 1
- retval = defaults.shift
- else
- raise Puppet::DevError, "Could not find a default provider for %s" %
- self.name
- end
-
- @defaultprovider = retval
- end
-
- return @defaultprovider
- end
-
- # Convert a hash, as provided by, um, a provider, into an instance of self.
- def self.hash2obj(hash)
- obj = nil
-
- namevar = self.namevar
- unless hash.include?(namevar) and hash[namevar]
- raise Puppet::DevError, "Hash was not passed with namevar"
- end
-
- # if the obj already exists with that name...
- if obj = self[hash[namevar]]
- # We're assuming here that objects with the same name
- # are the same object, which *should* be the case, assuming
- # we've set up our naming stuff correctly everywhere.
-
- # Mark found objects as present
- hash.each { |param, value|
- if property = obj.property(param)
- elsif val = obj[param]
- obj[param] = val
- else
- # There is a value on disk, but it should go away
- obj[param] = :absent
- end
- }
- else
- # create a new obj, since no existing one seems to
- # match
- obj = self.create(namevar => hash[namevar])
-
- # We can't just pass the hash in at object creation time,
- # because it sets the should value, not the is value.
- hash.delete(namevar)
- hash.each { |param, value|
- obj[param] = value unless obj.add_property_parameter(param)
- }
- end
-
- return obj
- end
-
- # Retrieve a provider by name.
- def self.provider(name)
- name = Puppet::Util.symbolize(name)
-
- # If we don't have it yet, try loading it.
- unless @providers.has_key?(name)
- @providerloader.load(name)
- end
- return @providers[name]
- end
-
- # Just list all of the providers.
- def self.providers
- @providers.keys
- end
-
- def self.validprovider?(name)
- name = Puppet::Util.symbolize(name)
-
- return (@providers.has_key?(name) && @providers[name].suitable?)
- end
-
- # Create a new provider of a type. This method must be called
- # directly on the type that it's implementing.
- def self.provide(name, options = {}, &block)
- name = Puppet::Util.symbolize(name)
-
- if obj = @providers[name]
- Puppet.debug "Reloading %s %s provider" % [name, self.name]
- unprovide(name)
- end
-
- parent = if pname = options[:parent]
- options.delete(:parent)
- if pname.is_a? Class
- pname
- else
- if provider = self.provider(pname)
- provider
- else
- raise Puppet::DevError,
- "Could not find parent provider %s of %s" %
- [pname, name]
- end
- end
- else
- Puppet::Provider
- end
-
- options[:resource_type] ||= self
-
- self.providify
-
- provider = genclass(name,
- :parent => parent,
- :hash => @providers,
- :prefix => "Provider",
- :block => block,
- :include => feature_module,
- :extend => feature_module,
- :attributes => options
- )
-
- return provider
- end
-
- # Make sure we have a :provider parameter defined. Only gets called if there
- # are providers.
- def self.providify
- return if @paramhash.has_key? :provider
-
- newparam(:provider) do
- desc "The specific backend for #{self.name.to_s} to use. You will
- seldom need to specify this -- Puppet will usually discover the
- appropriate provider for your platform."
-
- # This is so we can refer back to the type to get a list of
- # providers for documentation.
- class << self
- attr_accessor :parenttype
- end
-
- # We need to add documentation for each provider.
- def self.doc
- @doc + " Available providers are:\n\n" + parenttype().providers.sort { |a,b|
- a.to_s <=> b.to_s
- }.collect { |i|
- "* **%s**: %s" % [i, parenttype().provider(i).doc]
- }.join("\n")
- end
-
- defaultto {
- @resource.class.defaultprovider.name
- }
-
- validate do |provider_class|
- provider_class = provider_class[0] if provider_class.is_a? Array
- if provider_class.is_a?(Puppet::Provider)
- provider_class = provider_class.class.name
- end
-
- unless provider = @resource.class.provider(provider_class)
- raise ArgumentError, "Invalid %s provider '%s'" % [@resource.class.name, provider_class]
- end
- end
-
- munge do |provider|
- provider = provider[0] if provider.is_a? Array
- if provider.is_a? String
- provider = provider.intern
- end
- @resource.provider = provider
-
- if provider.is_a?(Puppet::Provider)
- provider.class.name
- else
- provider
- end
- end
- end.parenttype = self
- end
-
- def self.unprovide(name)
- if @providers.has_key? name
- rmclass(name,
- :hash => @providers,
- :prefix => "Provider"
- )
- if @defaultprovider and @defaultprovider.name == name
- @defaultprovider = nil
- end
- end
- end
-
- # Return an array of all of the suitable providers.
- def self.suitableprovider
- if @providers.empty?
- providerloader.loadall
- end
- @providers.find_all { |name, provider|
- provider.suitable?
- }.collect { |name, provider|
- provider
- }.reject { |p| p.name == :fake } # For testing
- end
-
- def provider=(name)
- if name.is_a?(Puppet::Provider)
- @provider = name
- @provider.resource = self
- elsif klass = self.class.provider(name)
- @provider = klass.new(self)
- else
- raise ArgumentError, "Could not find %s provider of %s" %
- [name, self.class.name]
- end
- end
-end
diff --git a/lib/puppet/metatype/tags.rb b/lib/puppet/metatype/tags.rb
deleted file mode 100644
index 1d96306dd..000000000
--- a/lib/puppet/metatype/tags.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-class Puppet::Type
- attr_reader :tags
-
- # Add a new tag.
- def tag(tag)
- tag = tag.intern if tag.is_a? String
- unless @tags.include? tag
- @tags << tag
- end
- end
-
- # Define the initial list of tags.
- def tags=(list)
- list = [list] unless list.is_a? Array
-
- @tags = list.collect do |t|
- case t
- when String: t.intern
- when Symbol: t
- else
- self.warning "Ignoring tag %s of type %s" % [tag.inspect, tag.class]
- end
- end
-
- @tags << self.class.name unless @tags.include?(self.class.name)
- end
-
- # Figure out of any of the specified tags apply to this object. This is an
- # OR operation.
- def tagged?(tags)
- tags = [tags] unless tags.is_a? Array
-
- tags = tags.collect { |t| t.intern }
-
- return tags.find { |tag| @tags.include? tag }
- end
-end
-
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index 544d94ea9..b34f2f8b0 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -19,6 +19,15 @@ class Puppet::Module
end
end
+ # Return an array of paths by splitting the +templatedir+ config
+ # parameter.
+ def self.templatepath(environment = nil)
+ dirs = Puppet.settings.value(:templatedir, environment).split(":")
+ dirs.select do |p|
+ p =~ /^#{File::SEPARATOR}/ && File::directory?(p)
+ end
+ end
+
# Find and return the +module+ that +path+ belongs to. If +path+ is
# absolute, or if there is no module whose name is the first component
# of +path+, return +nil+
@@ -63,25 +72,33 @@ class Puppet::Module
return template
end
+ template_paths = templatepath(environment)
+ default_template_path = File::join(template_paths.first, template)
+
# If we can find the template in :templatedir, we return that.
- td_file = File.join(Puppet.settings.value(:templatedir, environment), template)
- return td_file if File.exists?(td_file)
-
+ td_file = template_paths.collect { |path|
+ File::join(path, template)
+ }.find { |f| File.exists?(f) }
+
+ return td_file unless td_file == nil
+
+ td_file = find_template_for_module(template, environment)
+ td_file ||= default_template_path
+ end
+
+ def self.find_template_for_module(template, environment = nil)
path, file = split_path(template)
# Because templates don't have an assumed template name, like manifests do,
# we treat templates with no name as being templates in the main template
# directory.
- if file.nil?
- mod = nil
- else
+ if not file.nil?
mod = find(path, environment)
+ if mod
+ return mod.template(file)
+ end
end
- if mod
- return mod.template(file)
- else
- return td_file # Return this anyway, since we're going to fail.
- end
+ nil
end
# Return a list of manifests (as absolute filenames) that match +pat+
@@ -144,4 +161,5 @@ class Puppet::Module
end
private :initialize
+ private_class_method :find_template_for_module
end
diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb
index 5ca898dab..fe257db2b 100644
--- a/lib/puppet/network/client/master.rb
+++ b/lib/puppet/network/client/master.rb
@@ -198,6 +198,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
self.class.instance = self
@running = false
+ @splayed = false
end
# Mark that we should restart. The Puppet module checks whether we're running,
@@ -477,20 +478,19 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
@lockfile
end
+ def splayed?
+ @splayed
+ end
+
# Sleep when splay is enabled; else just return.
def splay
return unless Puppet[:splay]
+ return if splayed?
- limit = Integer(Puppet[:splaylimit])
-
- # Pick a splay time and then cache it.
- unless time = Puppet::Util::Storage.cache(:configuration)[:splay_time]
- time = rand(limit)
- Puppet::Util::Storage.cache(:configuration)[:splay_time] = time
- end
-
+ time = rand(Integer(Puppet[:splaylimit]))
Puppet.info "Sleeping for %s seconds (splay is enabled)" % time
sleep(time)
+ @splayed = true
end
private
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index 9682c460e..05ae7b9a2 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).
- Time.now
+ return 0
end
def initialize(hash = {})
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 3322a9ee7..77f1f0780 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -96,8 +96,10 @@ class Puppet::Node
# First, get the fqdn
unless fqdn = parameters["fqdn"]
- if domain = parameters["domain"]
- fqdn = parameters["hostname"] + "." + parameters["domain"]
+ if parameters["hostname"] and parameters["domain"]
+ fqdn = parameters["hostname"] + "." + parameters["domain"]
+ else
+ Puppet.warning "Host is missing hostname and/or domain: %s" % name
end
end
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index 31e009af5..f90193fc8 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -413,39 +413,12 @@ class Puppet::Parameter
@shadow = nil
end
- # This should only be called for parameters, but go ahead and make
- # it possible to call for properties, too.
- def value
- if self.is_a?(Puppet::Property)
- # We should return the 'is' value if there's not 'should'
- # value. This might be bad, though, because the 'should'
- # method knows whether to return an array or not and that info
- # is not exposed, and the 'is' value could be a symbol. I
- # can't seem to create a test in which this is a problem, but
- # that doesn't mean it's not one.
- if self.should
- return self.should
- else
- return self.retrieve
- end
- else
- if defined? @value
- return @value
- else
- return nil
- end
- end
- end
+ attr_reader :value
# Store the value provided. All of the checking should possibly be
# late-binding (e.g., users might not exist when the value is assigned
# but might when it is asked for).
def value=(value)
- # If we're a parameter, just hand the processing off to the should
- # method.
- if self.is_a?(Puppet::Property)
- return self.should = value
- end
if respond_to?(:validate)
validate(value)
end
diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb
index ee79159d7..a3094ac6e 100644
--- a/lib/puppet/parser/ast/vardef.rb
+++ b/lib/puppet/parser/ast/vardef.rb
@@ -3,7 +3,7 @@ require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
# Define a variable. Stores the value in the current scope.
class VarDef < AST::Branch
- attr_accessor :name, :value
+ attr_accessor :name, :value, :append
@settor = true
@@ -14,7 +14,7 @@ class Puppet::Parser::AST
value = @value.safeevaluate(scope)
parsewrap do
- scope.setvar(name,value, @file, @line)
+ scope.setvar(name,value, @file, @line, @append)
end
end
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index a2f6729ee..07666acb4 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -5,7 +5,7 @@
class Puppet::Parser::Parser
token LBRACK DQTEXT SQTEXT RBRACK LBRACE RBRACE SYMBOL FARROW COMMA TRUE
-token FALSE EQUALS LESSEQUAL NOTEQUAL DOT COLON LLCOLLECT RRCOLLECT
+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
@@ -58,6 +58,7 @@ statement: resource
| hostclass
| nodedef
| resourceoverride
+ | append
fstatement: NAME LPAREN funcvalues RPAREN {
args = aryfy(val[2])
@@ -291,6 +292,11 @@ assignment: VARIABLE EQUALS rvalue {
result = ast AST::VarDef, :name => variable, :value => val[2]
}
+append: VARIABLE APPENDS rvalue {
+ variable = ast AST::Name, :value => val[0]
+ result = ast AST::VarDef, :name => variable, :value => val[2], :append => true
+}
+
params: # nothing
{
result = ast AST::ASTArray
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 2c5f66e5a..71210d919 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -105,6 +105,7 @@ class Puppet::Parser::Lexer
'(' => :LPAREN,
')' => :RPAREN,
'=' => :EQUALS,
+ '+=' => :APPENDS,
'==' => :ISEQUAL,
'>=' => :GREATEREQUAL,
'>' => :GREATERTHAN,
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 3d7f21dca..69225cc2b 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..id9145566289', 'grammar.ra', 638
+module_eval <<'..end grammar.ra modeval..id7dbe8301d1', 'grammar.ra', 644
# It got too annoying having code in a file that needs to be compiled.
require 'puppet/parser/parser_support'
@@ -41,517 +41,525 @@ require 'puppet/parser/parser_support'
# $Id$
-..end grammar.ra modeval..id9145566289
+..end grammar.ra modeval..id7dbe8301d1
##### racc 1.4.5 generates ###
racc_reduce_table = [
0, 0, :racc_error,
- 1, 52, :_reduce_1,
- 1, 52, :_reduce_none,
+ 1, 53, :_reduce_1,
1, 53, :_reduce_none,
- 2, 53, :_reduce_4,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 4, 63, :_reduce_17,
- 3, 63, :_reduce_18,
- 2, 63, :_reduce_19,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 69, :_reduce_none,
- 3, 69, :_reduce_23,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_none,
- 1, 71, :_reduce_31,
+ 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,
- 3, 70, :_reduce_33,
- 5, 56, :_reduce_34,
- 5, 56, :_reduce_35,
- 5, 56, :_reduce_36,
- 5, 67, :_reduce_37,
- 2, 57, :_reduce_38,
- 1, 87, :_reduce_39,
- 2, 87, :_reduce_40,
- 2, 58, :_reduce_41,
- 3, 88, :_reduce_42,
- 3, 88, :_reduce_43,
- 1, 89, :_reduce_none,
- 1, 89, :_reduce_none,
- 3, 89, :_reduce_46,
- 1, 90, :_reduce_none,
- 3, 90, :_reduce_48,
+ 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, 92, :_reduce_51,
- 3, 92, :_reduce_52,
+ 3, 91, :_reduce_47,
+ 1, 92, :_reduce_none,
+ 3, 92, :_reduce_49,
1, 93, :_reduce_none,
1, 93, :_reduce_none,
- 4, 95, :_reduce_55,
- 1, 81, :_reduce_none,
- 3, 81, :_reduce_57,
- 0, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 97, :_reduce_60,
- 1, 72, :_reduce_61,
+ 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, 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,
+ 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,
- 3, 59, :_reduce_69,
- 0, 83, :_reduce_70,
- 1, 83, :_reduce_71,
- 3, 83, :_reduce_72,
- 3, 100, :_reduce_73,
- 3, 101, :_reduce_74,
- 1, 102, :_reduce_none,
- 1, 102, :_reduce_none,
- 0, 86, :_reduce_77,
- 1, 86, :_reduce_78,
- 3, 86, :_reduce_79,
- 1, 103, :_reduce_none,
- 3, 103, :_reduce_81,
- 1, 94, :_reduce_none,
- 1, 94, :_reduce_none,
- 1, 94, :_reduce_none,
- 1, 94, :_reduce_none,
- 1, 94, :_reduce_none,
- 1, 94, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 1, 99, :_reduce_none,
- 4, 76, :_reduce_98,
- 3, 76, :_reduce_99,
- 1, 78, :_reduce_100,
- 1, 78, :_reduce_101,
- 1, 75, :_reduce_102,
- 4, 79, :_reduce_103,
- 4, 79, :_reduce_104,
- 6, 61, :_reduce_105,
- 0, 106, :_reduce_none,
- 4, 106, :_reduce_107,
- 1, 105, :_reduce_none,
- 5, 60, :_reduce_109,
+ 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,
- 2, 107, :_reduce_111,
- 5, 108, :_reduce_112,
- 4, 108, :_reduce_113,
+ 5, 61, :_reduce_111,
1, 109, :_reduce_none,
- 3, 109, :_reduce_115,
- 3, 77, :_reduce_116,
+ 2, 109, :_reduce_113,
+ 5, 110, :_reduce_114,
+ 4, 110, :_reduce_115,
1, 111, :_reduce_none,
- 4, 111, :_reduce_118,
+ 3, 111, :_reduce_117,
+ 3, 79, :_reduce_118,
1, 113, :_reduce_none,
- 3, 113, :_reduce_120,
- 3, 112, :_reduce_121,
- 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_129,
- 1, 114, :_reduce_130,
- 3, 114, :_reduce_131,
- 2, 62, :_reduce_132,
- 6, 64, :_reduce_133,
- 5, 64, :_reduce_134,
+ 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, 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,
- 1, 85, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 117, :_reduce_none,
- 3, 117, :_reduce_143,
- 1, 119, :_reduce_none,
- 1, 119, :_reduce_none,
- 1, 119, :_reduce_none,
+ 6, 67, :_reduce_139,
+ 5, 67, :_reduce_140,
+ 1, 87, :_reduce_none,
+ 1, 82, :_reduce_none,
+ 1, 82, :_reduce_none,
1, 119, :_reduce_none,
- 0, 54, :_reduce_148,
- 0, 120, :_reduce_149,
- 1, 115, :_reduce_none,
- 3, 115, :_reduce_151,
- 3, 115, :_reduce_152,
+ 3, 119, :_reduce_145,
1, 121, :_reduce_none,
- 3, 121, :_reduce_154,
- 3, 122, :_reduce_155,
- 1, 122, :_reduce_156,
- 3, 122, :_reduce_157,
- 1, 122, :_reduce_158,
- 1, 118, :_reduce_none,
- 2, 118, :_reduce_160,
- 1, 116, :_reduce_none,
- 2, 116, :_reduce_162,
- 1, 123, :_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,
- 1, 73, :_reduce_165,
- 3, 98, :_reduce_166,
- 2, 98, :_reduce_167,
- 1, 104, :_reduce_none,
- 1, 104, :_reduce_none,
- 0, 84, :_reduce_none,
- 1, 84, :_reduce_171 ]
+ 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,
+ 1, 118, :_reduce_none,
+ 2, 118, :_reduce_164,
+ 1, 125, :_reduce_none,
+ 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 ]
-racc_reduce_n = 172
+racc_reduce_n = 174
-racc_shift_n = 276
+racc_shift_n = 279
racc_action_table = [
- 71, 51, 53, 184, 162, 102, 71, 51, 53, 132,
- 149, 5, 209, 47, -127, 87, 71, 51, 53, 88,
- 208, 65, 71, 51, 53, 162, 144, 34, 35, 99,
- 65, 89, 126, -127, 50, 54, 65, 126, 59, -123,
- 50, 54, 207, 45, 59, 161, 65, 56, -126, 45,
- 50, 54, 65, 56, 59, 90, 50, 54, 185, 45,
- 59, 36, 169, 56, 37, 45, 71, 51, 53, 56,
- 204, 206, 47, 51, 53, 200, 149, 51, 53, 33,
- 199, -122, 71, 51, 53, 238, 1, 65, 71, 51,
- 53, 67, 144, 34, 35, 87, 65, 237, 234, -123,
- 50, 54, 65, 200, 59, 233, 50, 54, 199, 45,
- 59, 252, 65, 56, 43, 45, 50, 54, 65, 56,
- 59, 33, 50, 54, 156, 45, 59, 36, 1, 56,
- 37, 45, 71, 51, 53, 56, 204, 206, 71, 51,
- 53, 149, 149, 34, 35, 188, 259, 196, 71, 51,
- 53, -125, 65, 65, 71, 51, 53, 144, 144, 51,
- 53, 202, 65, 162, 33, 168, 50, 54, 65, 137,
- 59, 1, 50, 54, 168, 45, 59, 36, 65, 56,
- 37, 45, 50, 174, 65, 56, 59, -122, 50, 54,
- 165, 111, 59, -125, -122, 56, 127, 45, 71, 51,
- 53, 56, 33, 211, 71, 51, 53, 204, 206, 1,
- 5, 135, 218, 186, 71, 51, 53, 188, 189, 106,
- 125, 51, 53, 221, 222, 231, 140, 140, 65, 225,
- 126, -124, 50, 54, 65, 228, 59, 47, 50, 54,
- -139, 45, 59, 123, 65, 56, 106, 45, 50, 112,
- 65, 56, 59, -124, 50, 174, 134, 111, 59, 51,
- 53, 56, 164, 111, 239, 51, 53, 56, 240, 241,
- 242, -124, 96, 140, -126, 51, 53, 93, 179, 168,
- 91, 51, 53, 159, 181, 260, 262, 85, 65, 157,
- 88, 133, 50, 174, 65, 41, 59, -124, 50, 54,
- 128, 111, 59, -122, 65, 56, 43, 45, 50, 174,
- 65, 56, 59, -125, 50, 54, -123, 111, 59, 51,
- 53, 56, 43, 45, -127, 51, 53, 56, 176, 40,
- 269, -171, 270, -128, -123, 51, 53, 152, -125, nil,
- nil, 51, 53, nil, nil, nil, nil, nil, 65, nil,
- nil, nil, 50, 174, 65, nil, 59, nil, 50, 174,
- 43, 111, 59, nil, 65, 56, nil, 111, 50, 174,
- 65, 56, 59, 254, 50, 174, nil, 111, 59, 51,
- 53, 56, nil, 111, nil, 51, 53, 56, nil, nil,
- nil, nil, nil, 15, nil, 19, 21, nil, 28, 2,
- nil, 8, nil, 13, nil, 17, nil, 22, 65, nil,
- 1, 5, 50, 174, 65, 264, 59, nil, 50, 174,
- nil, 111, 59, nil, nil, 56, nil, 111, nil, nil,
- nil, 56, nil, nil, 271, 15, nil, 19, 21, nil,
- 28, 2, nil, 8, nil, 13, nil, 17, nil, 22,
- nil, nil, 1, 5, 15, 212, 19, 21, nil, 28,
- 2, nil, 8, nil, 13, nil, 17, nil, 22, nil,
- nil, 1, 5, nil, 230, 15, nil, 19, 21, nil,
- 28, 2, nil, 8, nil, 13, nil, 17, nil, 22,
- nil, nil, 1, 5, 15, 253, 19, 21, nil, 28,
- 2, nil, 8, nil, 13, nil, 17, nil, 22, nil,
- nil, 1, 5, nil, 214, 15, nil, 19, 21, nil,
- 28, 2, nil, 8, nil, 13, nil, 17, nil, 22,
- nil, nil, 1, 5, 15, 274, 19, 21, nil, 28,
- 2, nil, 8, nil, 13, nil, 17, nil, 22, nil,
- nil, 1, 5, nil, 235, 15, nil, 19, 21, nil,
- 28, 2, nil, 8, nil, 13, nil, 17, nil, 22,
- nil, nil, 1, 5, 15, 275, 19, 21, nil, 28,
- 2, nil, 8, nil, 13, nil, 17, nil, 22, nil,
- nil, 1, 5, nil, nil, 15, nil, 19, 21, nil,
- 28, 2, nil, 8, nil, 13, nil, 17, nil, 22,
- nil, nil, 1, 5, 15, nil, 19, 21, nil, 28,
- 2, nil, 8, nil, 13, nil, 17, nil, 22, nil,
- nil, 1, 5, 15, nil, 19, 21, nil, 28, 2,
- nil, 8, nil, 13, nil, 17, nil, 22, nil, nil,
- 1, 5, 15, nil, 19, 21, nil, 28, 2, nil,
- 8, nil, 13, nil, 17, nil, 22, nil, nil, 1,
- 5, 15, nil, 19, 21, nil, 28, 2, nil, 8,
- nil, 13, nil, 17, nil, 22, nil, nil, 1, 5 ]
+ 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 ]
racc_action_check = [
- 93, 93, 93, 127, 106, 38, 71, 71, 71, 71,
- 90, 127, 146, 54, 78, 23, 87, 87, 87, 23,
- 146, 90, 161, 161, 161, 112, 90, 102, 102, 38,
- 93, 23, 54, 64, 93, 93, 71, 112, 93, 62,
- 71, 71, 142, 93, 71, 106, 87, 93, 66, 71,
- 87, 87, 161, 71, 87, 23, 161, 161, 129, 87,
- 161, 102, 119, 87, 102, 161, 240, 240, 240, 161,
- 142, 142, 13, 13, 13, 238, 149, 135, 135, 2,
- 238, 74, 15, 15, 15, 197, 2, 149, 17, 17,
- 17, 13, 149, 99, 99, 61, 240, 197, 194, 118,
- 240, 240, 13, 137, 240, 194, 13, 13, 137, 240,
- 13, 210, 15, 240, 13, 13, 15, 15, 17, 13,
- 15, 96, 17, 17, 96, 15, 17, 99, 96, 15,
- 99, 17, 239, 239, 239, 17, 210, 210, 162, 162,
- 162, 89, 205, 8, 8, 227, 227, 136, 165, 165,
- 165, 116, 89, 205, 47, 47, 47, 89, 205, 19,
- 19, 139, 239, 140, 21, 141, 239, 239, 162, 84,
- 239, 21, 162, 162, 115, 239, 162, 8, 165, 239,
- 8, 162, 165, 165, 47, 162, 165, 114, 47, 47,
- 113, 165, 47, 60, 58, 165, 55, 47, 225, 225,
- 225, 47, 29, 151, 187, 187, 187, 151, 151, 29,
- 29, 83, 163, 131, 41, 41, 41, 131, 131, 164,
- 52, 192, 192, 166, 167, 192, 168, 169, 225, 170,
- 174, 46, 225, 225, 187, 182, 225, 184, 187, 187,
- 45, 225, 187, 42, 41, 225, 40, 187, 41, 41,
- 192, 187, 41, 110, 192, 192, 81, 41, 192, 208,
- 208, 41, 107, 192, 199, 126, 126, 192, 200, 201,
- 203, 70, 32, 88, 79, 209, 209, 28, 124, 224,
- 25, 67, 67, 100, 126, 230, 233, 22, 208, 97,
- 95, 73, 208, 208, 126, 11, 208, 245, 126, 126,
- 67, 208, 126, 246, 209, 208, 126, 126, 209, 209,
- 67, 126, 209, 248, 67, 67, 249, 209, 67, 125,
- 125, 209, 67, 67, 250, 123, 123, 67, 123, 9,
- 258, 259, 260, 77, 76, 176, 176, 91, 75, nil,
- nil, 134, 134, nil, nil, nil, nil, nil, 125, nil,
- nil, nil, 125, 125, 123, nil, 125, nil, 123, 123,
- 125, 125, 123, nil, 176, 125, nil, 123, 176, 176,
- 134, 123, 176, 215, 134, 134, nil, 176, 134, 234,
- 234, 176, nil, 134, nil, 257, 257, 134, nil, nil,
- nil, nil, nil, 215, nil, 215, 215, nil, 215, 215,
- nil, 215, nil, 215, nil, 215, nil, 215, 234, nil,
- 215, 215, 234, 234, 257, 236, 234, nil, 257, 257,
- nil, 234, 257, nil, nil, 234, nil, 257, nil, nil,
- nil, 257, nil, nil, 262, 236, nil, 236, 236, nil,
- 236, 236, nil, 236, nil, 236, nil, 236, nil, 236,
- nil, nil, 236, 236, 262, 157, 262, 262, nil, 262,
- 262, nil, 262, nil, 262, nil, 262, nil, 262, nil,
- nil, 262, 262, nil, 190, 157, nil, 157, 157, nil,
- 157, 157, nil, 157, nil, 157, nil, 157, nil, 157,
- nil, nil, 157, 157, 190, 213, 190, 190, nil, 190,
- 190, nil, 190, nil, 190, nil, 190, nil, 190, nil,
- nil, 190, 190, nil, 159, 213, nil, 213, 213, nil,
- 213, 213, nil, 213, nil, 213, nil, 213, nil, 213,
- nil, nil, 213, 213, 159, 272, 159, 159, nil, 159,
- 159, nil, 159, nil, 159, nil, 159, nil, 159, nil,
- nil, 159, 159, nil, 196, 272, nil, 272, 272, nil,
- 272, 272, nil, 272, nil, 272, nil, 272, nil, 272,
- nil, nil, 272, 272, 196, 273, 196, 196, nil, 196,
- 196, nil, 196, nil, 196, nil, 196, nil, 196, nil,
- nil, 196, 196, nil, nil, 273, nil, 273, 273, nil,
- 273, 273, nil, 273, nil, 273, nil, 273, nil, 273,
- nil, nil, 273, 273, 133, nil, 133, 133, nil, 133,
- 133, nil, 133, nil, 133, nil, 133, nil, 133, nil,
- nil, 133, 133, 270, nil, 270, 270, nil, 270, 270,
- nil, 270, nil, 270, nil, 270, nil, 270, nil, nil,
- 270, 270, 27, nil, 27, 27, nil, 27, 27, nil,
- 27, nil, 27, nil, 27, nil, 27, nil, nil, 27,
- 27, 0, nil, 0, 0, nil, 0, 0, nil, 0,
- nil, 0, nil, 0, nil, 0, nil, nil, 0, 0 ]
+ 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,
+ nil, 0, 0, nil, 0, nil, 0, nil, 0, nil,
+ 0, nil, nil, 0, 0 ]
racc_action_pointer = [
- 644, nil, 42, nil, nil, nil, nil, nil, 140, 323,
- nil, 289, nil, 70, nil, 80, nil, 86, nil, 156,
- nil, 127, 246, 13, nil, 280, nil, 625, 264, 165,
- nil, nil, 238, nil, nil, nil, nil, nil, -5, nil,
- 209, 212, 223, nil, nil, 238, 211, 152, nil, nil,
- nil, nil, 210, nil, 11, 186, nil, nil, 174, nil,
- 173, 93, 19, nil, 13, nil, 28, 278, nil, nil,
- 251, 4, nil, 285, 61, 318, 314, 313, -6, 254,
- nil, 250, nil, 201, 148, nil, nil, 14, 236, 120,
- -11, 337, nil, -2, nil, 284, 84, 283, nil, 90,
- 277, nil, 24, nil, nil, nil, -5, 252, nil, nil,
- 233, nil, 16, 152, 167, 164, 131, nil, 79, 45,
- nil, nil, nil, 322, 273, 316, 262, -34, nil, 36,
- nil, 208, nil, 587, 338, 74, 141, 71, nil, 156,
- 154, 155, 23, nil, nil, nil, -3, nil, nil, 55,
- nil, 160, nil, nil, nil, nil, nil, 448, nil, 507,
- nil, 20, 136, 205, 182, 146, 216, 217, 189, 190,
- 220, nil, nil, nil, 209, nil, 332, nil, nil, nil,
- nil, nil, 213, nil, 235, nil, nil, 202, nil, nil,
- 467, nil, 218, nil, 88, nil, 547, 75, nil, 251,
- 255, 247, nil, 263, nil, 121, nil, nil, 256, 272,
- 89, nil, nil, 488, nil, 366, nil, nil, nil, nil,
- nil, nil, nil, nil, 269, 196, nil, 136, nil, nil,
- 257, nil, nil, 280, 376, nil, 408, nil, 43, 130,
- 64, nil, nil, nil, nil, 277, 283, nil, 293, 296,
- 304, nil, nil, nil, nil, nil, nil, 382, 323, 324,
- 326, nil, 427, nil, nil, nil, nil, nil, nil, nil,
- 606, nil, 528, 568, nil, nil ]
+ 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 ]
racc_action_default = [
- -148, -141, -172, -15, -3, -139, -16, -5, -172, -172,
- -6, -172, -7, -140, -8, -172, -9, -172, -10, -172,
- -11, -172, -39, -172, -12, -172, -13, -1, -172, -172,
- -14, -2, -148, -140, -146, -145, -144, -147, -148, -142,
- -77, -70, -172, -31, -29, -62, -30, -172, -32, -19,
- -102, -100, -20, -101, -61, -21, -60, -22, -24, -129,
- -25, -172, -26, -128, -27, -165, -28, -172, -108, -92,
- -88, -172, -95, -172, -89, -93, -90, -97, -91, -96,
- -94, -172, -130, -132, -148, -40, -41, -172, -70, -148,
- -148, -172, -4, -172, -38, -172, -172, -172, -161, -172,
- -172, -159, -172, -75, -76, -78, -172, -170, -66, -71,
- -63, -62, -61, -58, -64, -170, -67, -56, -65, -172,
- -127, -126, -68, -172, -172, -172, -172, -172, -18, -172,
- -80, -172, -167, -172, -172, -172, -172, -149, -150, -172,
- -172, -170, -172, -45, -61, -47, -172, -54, -53, -148,
- -44, -172, 276, -69, -162, -163, -164, -172, -160, -172,
- -143, -172, -172, -172, -171, -59, -172, -172, -171, -70,
- -172, -124, -116, -117, -61, -122, -172, -125, -123, -103,
- -23, -99, -172, -33, -172, -17, -166, -172, -168, -169,
- -172, -114, -172, -110, -172, -131, -172, -172, -153, -156,
- -158, -172, -104, -172, -50, -172, -49, -43, -172, -172,
- -172, -42, -136, -172, -138, -172, -74, -73, -37, -79,
- -57, -34, -35, -72, -170, -172, -119, -170, -98, -81,
- -106, -109, -111, -172, -172, -134, -172, -152, -172, -172,
- -172, -151, -36, -46, -86, -82, -83, -51, -87, -84,
- -85, -52, -48, -135, -137, -55, -121, -172, -172, -169,
- -172, -105, -172, -115, -133, -154, -155, -157, -120, -118,
- -172, -113, -172, -172, -112, -107 ]
+ -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 ]
racc_goto_table = [
- 23, 27, 122, 92, 173, 105, 198, 49, 117, 46,
- 187, 39, 31, 170, 32, 82, 193, 103, 115, 25,
- 142, 151, 243, 44, 191, 247, 251, 23, 131, 95,
- 64, 86, 73, 84, 261, 192, 107, 110, 166, 172,
- 113, 227, 83, 62, 98, 163, 136, 97, 38, 100,
- 101, 108, 180, 167, 201, 197, 94, 226, 120, 154,
- nil, 129, nil, 46, 66, 141, 170, nil, nil, nil,
- nil, 118, nil, nil, 232, nil, nil, 44, nil, 203,
- 210, nil, 191, nil, 64, nil, nil, nil, nil, nil,
- nil, nil, 121, nil, nil, nil, 138, 62, nil, nil,
- nil, nil, 158, nil, nil, 160, 257, 265, 155, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 66, 171,
- 182, 46, 46, nil, 263, nil, 122, nil, nil, 219,
- 171, 195, 220, 23, 190, 44, 44, nil, 268, nil,
- 120, 103, 64, 64, nil, 223, 224, 170, nil, nil,
- nil, 120, nil, 178, nil, 62, 62, 23, 213, 23,
- 215, 110, 255, nil, 178, 258, 92, nil, nil, nil,
- 60, nil, 171, nil, 121, 108, 66, 66, nil, nil,
- 58, nil, 120, nil, nil, 121, nil, nil, 171, 92,
- 23, 92, nil, 120, nil, 118, 23, 236, 116, nil,
- nil, nil, nil, nil, 245, 245, 178, nil, 114, 120,
- nil, nil, 92, 23, nil, 23, 121, nil, 244, 244,
- nil, nil, 178, nil, 60, 250, 250, 121, nil, nil,
- 171, nil, nil, nil, 58, nil, 23, nil, 249, 249,
- nil, nil, nil, 121, nil, nil, 148, 148, 92, 92,
- nil, 120, nil, 171, nil, nil, 147, 147, nil, 121,
- 121, nil, 23, 272, 178, nil, nil, nil, nil, nil,
- 23, 273, 23, 23, 120, 68, nil, 81, nil, 77,
- 177, 77, 60, 60, 48, 121, 72, 178, 72, nil,
- 175, 177, 58, 58, nil, nil, nil, nil, nil, nil,
- nil, 175, nil, nil, nil, nil, 148, 124, 121, nil,
- nil, 77, nil, nil, nil, nil, 147, nil, 72, nil,
- nil, nil, 116, nil, nil, nil, nil, nil, nil, nil,
- nil, 130, 114, 177, nil, 77, nil, nil, 48, nil,
- nil, nil, 72, 175, nil, nil, nil, 139, nil, 177,
- nil, 77, nil, 153, nil, nil, nil, 77, 72, 175,
- nil, nil, 148, nil, 72, 248, 248, nil, nil, nil,
- nil, nil, 147, nil, nil, 246, 246, nil, nil, nil,
+ 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,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 177, nil, nil, nil, nil, nil, 48, 183, nil,
- nil, 175, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 177, nil, nil, nil, nil, nil,
- nil, 216, 217, nil, 175, 77, 77, nil, nil, nil,
- nil, nil, 72, 72, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 229, nil, nil,
- nil, 77, nil, nil, nil, nil, nil, nil, 72, 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, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 256, nil, nil, nil, 77,
- nil, nil, nil, nil, nil, nil, 72, nil, nil, 266,
- 267, nil, nil, 77, 77, nil, nil, nil, nil, nil,
- 72, 72 ]
+ nil, nil, nil, nil, 180, nil, nil, 73, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 73, nil, nil,
+ nil, 73 ]
racc_goto_check = [
- 34, 2, 47, 4, 61, 51, 71, 17, 44, 27,
- 53, 68, 3, 59, 29, 27, 57, 49, 32, 1,
- 38, 38, 39, 26, 59, 43, 43, 34, 52, 34,
- 24, 37, 54, 29, 55, 56, 35, 27, 31, 60,
- 30, 62, 63, 23, 3, 33, 64, 65, 66, 67,
- 3, 26, 20, 33, 69, 70, 5, 61, 24, 72,
- nil, 17, nil, 27, 25, 32, 59, nil, nil, nil,
- nil, 23, nil, nil, 57, nil, nil, 26, nil, 33,
- 38, nil, 59, nil, 24, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, nil, nil, 3, 23, nil, nil,
- nil, nil, 68, nil, nil, 68, 53, 71, 29, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, 27,
- 17, 27, 27, nil, 59, nil, 47, nil, nil, 51,
- 27, 27, 44, 34, 2, 26, 26, nil, 61, nil,
- 24, 49, 24, 24, nil, 49, 32, 59, nil, nil,
- nil, 24, nil, 23, nil, 23, 23, 34, 2, 34,
- 2, 27, 33, nil, 23, 33, 4, nil, nil, nil,
- 22, nil, 27, nil, 25, 26, 25, 25, nil, nil,
- 21, nil, 24, nil, nil, 25, nil, nil, 27, 4,
- 34, 4, nil, 24, nil, 23, 34, 2, 22, nil,
- nil, nil, nil, nil, 27, 27, 23, nil, 21, 24,
- nil, nil, 4, 34, nil, 34, 25, nil, 26, 26,
- nil, nil, 23, nil, 22, 24, 24, 25, nil, nil,
- 27, nil, nil, nil, 21, nil, 34, nil, 23, 23,
- nil, nil, nil, 25, nil, nil, 22, 22, 4, 4,
- nil, 24, nil, 27, nil, nil, 21, 21, nil, 25,
- 25, nil, 34, 2, 23, nil, nil, nil, nil, nil,
- 34, 2, 34, 34, 24, 48, nil, 48, nil, 46,
- 22, 46, 22, 22, 28, 25, 28, 23, 28, nil,
- 21, 22, 21, 21, nil, nil, nil, nil, nil, nil,
- nil, 21, nil, nil, nil, nil, 22, 48, 25, nil,
- nil, 46, nil, nil, nil, nil, 21, nil, 28, nil,
- nil, nil, 22, nil, nil, nil, nil, nil, nil, nil,
- nil, 48, 21, 22, nil, 46, nil, nil, 28, nil,
- nil, nil, 28, 21, nil, nil, nil, 48, nil, 22,
- nil, 46, nil, 48, nil, nil, nil, 46, 28, 21,
- nil, nil, 22, nil, 28, 22, 22, nil, nil, nil,
- nil, nil, 21, nil, nil, 21, 21, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 22, nil, nil, nil, nil, nil, 28, 28, nil,
- nil, 21, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 22, nil, nil, nil, nil, nil,
- nil, 48, 48, nil, 21, 46, 46, nil, nil, nil,
- nil, nil, 28, 28, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 48, nil, nil,
- nil, 46, nil, nil, nil, nil, nil, nil, 28, nil,
+ 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,
+ 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, 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, nil, 48, nil, nil, nil, 46,
- nil, nil, nil, nil, nil, nil, 28, nil, nil, 48,
- 48, nil, nil, 46, 46, nil, nil, nil, nil, nil,
- 28, 28 ]
+ nil, nil, nil, nil, 22, nil, nil, 47, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 47, nil, nil,
+ nil, 47 ]
racc_goto_pointer = [
- nil, 19, 1, 12, -24, 27, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -6, nil, nil,
- -73, 167, 157, 30, 17, 51, 10, -4, 271, 12,
- -1, -75, -23, -62, 0, -4, nil, 8, -69, -183,
- nil, nil, nil, -183, -33, nil, 264, -39, 260, -23,
- nil, -35, -43, -121, 17, -196, -99, -118, nil, -110,
- -84, -119, -135, 23, -38, 15, 40, 11, 3, -83,
- -82, -131, -37 ]
+ 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 ]
racc_goto_default = [
- nil, nil, nil, 150, 4, 7, 10, 12, 14, 16,
- 18, 20, 24, 26, 30, 3, 6, nil, 52, 55,
- 57, 74, 75, 76, 78, 79, 69, 70, 9, 11,
- nil, nil, nil, nil, 61, nil, 29, nil, nil, 143,
- 205, 145, 146, nil, nil, 119, 63, 80, nil, 109,
- 104, nil, nil, nil, nil, nil, nil, nil, 194, 42,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil ]
+ 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, nil ]
racc_token_table = {
false => 0,
@@ -568,47 +576,48 @@ racc_token_table = {
:TRUE => 11,
:FALSE => 12,
:EQUALS => 13,
- :LESSEQUAL => 14,
- :NOTEQUAL => 15,
- :DOT => 16,
- :COLON => 17,
- :LLCOLLECT => 18,
- :RRCOLLECT => 19,
- :QMARK => 20,
- :LPAREN => 21,
- :RPAREN => 22,
- :ISEQUAL => 23,
- :GREATEREQUAL => 24,
- :GREATERTHAN => 25,
- :LESSTHAN => 26,
- :IF => 27,
- :ELSE => 28,
- :IMPORT => 29,
- :DEFINE => 30,
- :ELSIF => 31,
- :VARIABLE => 32,
- :CLASS => 33,
- :INHERITS => 34,
- :NODE => 35,
- :BOOLEAN => 36,
- :NAME => 37,
- :SEMIC => 38,
- :CASE => 39,
- :DEFAULT => 40,
- :AT => 41,
- :LCOLLECT => 42,
- :RCOLLECT => 43,
- :CLASSNAME => 44,
- :CLASSREF => 45,
- :NOT => 46,
- :OR => 47,
- :AND => 48,
- :UNDEF => 49,
- :PARROW => 50 }
+ :APPENDS => 14,
+ :LESSEQUAL => 15,
+ :NOTEQUAL => 16,
+ :DOT => 17,
+ :COLON => 18,
+ :LLCOLLECT => 19,
+ :RRCOLLECT => 20,
+ :QMARK => 21,
+ :LPAREN => 22,
+ :RPAREN => 23,
+ :ISEQUAL => 24,
+ :GREATEREQUAL => 25,
+ :GREATERTHAN => 26,
+ :LESSTHAN => 27,
+ :IF => 28,
+ :ELSE => 29,
+ :IMPORT => 30,
+ :DEFINE => 31,
+ :ELSIF => 32,
+ :VARIABLE => 33,
+ :CLASS => 34,
+ :INHERITS => 35,
+ :NODE => 36,
+ :BOOLEAN => 37,
+ :NAME => 38,
+ :SEMIC => 39,
+ :CASE => 40,
+ :DEFAULT => 41,
+ :AT => 42,
+ :LCOLLECT => 43,
+ :RCOLLECT => 44,
+ :CLASSNAME => 45,
+ :CLASSREF => 46,
+ :NOT => 47,
+ :OR => 48,
+ :AND => 49,
+ :UNDEF => 50,
+ :PARROW => 51 }
racc_use_result_var = true
-racc_nt_base = 51
+racc_nt_base = 52
Racc_arg = [
racc_action_table,
@@ -641,6 +650,7 @@ Racc_token_to_s_table = [
'TRUE',
'FALSE',
'EQUALS',
+'APPENDS',
'LESSEQUAL',
'NOTEQUAL',
'DOT',
@@ -695,6 +705,7 @@ Racc_token_to_s_table = [
'hostclass',
'nodedef',
'resourceoverride',
+'append',
'funcvalues',
'namestrings',
'resourcerefs',
@@ -823,8 +834,10 @@ module_eval <<'.,.,', 'grammar.ra', 46
# reduce 16 omitted
-module_eval <<'.,.,', 'grammar.ra', 68
- def _reduce_17( val, _values, result )
+ # reduce 17 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 69
+ def _reduce_18( val, _values, result )
args = aryfy(val[2])
result = ast AST::Function,
:name => val[0],
@@ -834,8 +847,8 @@ module_eval <<'.,.,', 'grammar.ra', 68
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 74
- def _reduce_18( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 75
+ def _reduce_19( val, _values, result )
result = ast AST::Function,
:name => val[0],
:arguments => AST::ASTArray.new({}),
@@ -844,8 +857,8 @@ module_eval <<'.,.,', 'grammar.ra', 74
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 81
- def _reduce_19( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 82
+ def _reduce_20( val, _values, result )
args = aryfy(val[1])
result = ast AST::Function,
:name => val[0],
@@ -855,14 +868,14 @@ module_eval <<'.,.,', 'grammar.ra', 81
end
.,.,
- # reduce 20 omitted
-
# reduce 21 omitted
# reduce 22 omitted
-module_eval <<'.,.,', 'grammar.ra', 91
- def _reduce_23( val, _values, result )
+ # reduce 23 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 92
+ def _reduce_24( val, _values, result )
result = aryfy(val[0], val[2])
result.line = @lexer.line
result.file = @lexer.file
@@ -870,8 +883,6 @@ module_eval <<'.,.,', 'grammar.ra', 91
end
.,.,
- # reduce 24 omitted
-
# reduce 25 omitted
# reduce 26 omitted
@@ -884,17 +895,19 @@ module_eval <<'.,.,', 'grammar.ra', 91
# reduce 30 omitted
-module_eval <<'.,.,', 'grammar.ra', 104
- def _reduce_31( val, _values, result )
+ # reduce 31 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 105
+ def _reduce_32( val, _values, result )
result = ast AST::Name, :value => val[0]
result
end
.,.,
- # reduce 32 omitted
+ # reduce 33 omitted
-module_eval <<'.,.,', 'grammar.ra', 115
- def _reduce_33( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 116
+ def _reduce_34( val, _values, result )
unless val[0].is_a?(AST::ASTArray)
val[0] = aryfy(val[0])
end
@@ -906,8 +919,8 @@ module_eval <<'.,.,', 'grammar.ra', 115
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 136
- def _reduce_34( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 137
+ def _reduce_35( val, _values, result )
array = val[2]
if array.instance_of?(AST::ResourceInstance)
array = [array]
@@ -930,31 +943,31 @@ module_eval <<'.,.,', 'grammar.ra', 136
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 139
- def _reduce_35( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 140
+ def _reduce_36( val, _values, result )
# This is a deprecated syntax.
error "All resource specifications require names"
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 142
- def _reduce_36( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 143
+ def _reduce_37( val, _values, result )
# a defaults setting for a type
result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2])
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 147
- def _reduce_37( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 148
+ def _reduce_38( val, _values, result )
result = ast AST::ResourceOverride, :object => val[0], :params => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 174
- def _reduce_38( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 175
+ def _reduce_39( val, _values, result )
type = val[0]
if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
@@ -981,22 +994,22 @@ module_eval <<'.,.,', 'grammar.ra', 174
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 175
- def _reduce_39( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 176
+ def _reduce_40( val, _values, result )
result = :virtual
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 176
- def _reduce_40( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 177
+ def _reduce_41( val, _values, result )
result = :exported
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 199
- def _reduce_41( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 200
+ def _reduce_42( val, _values, result )
if val[0] =~ /^[a-z]/
Puppet.warning addcontext("Collection names must now be capitalized")
end
@@ -1018,8 +1031,8 @@ module_eval <<'.,.,', 'grammar.ra', 199
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 209
- def _reduce_42( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 210
+ def _reduce_43( val, _values, result )
if val[1]
result = val[1]
result.form = :virtual
@@ -1030,8 +1043,8 @@ module_eval <<'.,.,', 'grammar.ra', 209
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 217
- def _reduce_43( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 218
+ def _reduce_44( val, _values, result )
if val[1]
result = val[1]
result.form = :exported
@@ -1042,33 +1055,33 @@ module_eval <<'.,.,', 'grammar.ra', 217
end
.,.,
- # reduce 44 omitted
-
# reduce 45 omitted
-module_eval <<'.,.,', 'grammar.ra', 225
- def _reduce_46( val, _values, result )
+ # reduce 46 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 226
+ def _reduce_47( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
result
end
.,.,
- # reduce 47 omitted
+ # reduce 48 omitted
-module_eval <<'.,.,', 'grammar.ra', 231
- def _reduce_48( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 232
+ def _reduce_49( val, _values, result )
result = val[1]
result.parens = true
result
end
.,.,
- # reduce 49 omitted
-
# reduce 50 omitted
-module_eval <<'.,.,', 'grammar.ra', 239
- def _reduce_51( val, _values, result )
+ # reduce 51 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 240
+ def _reduce_52( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
#result = ast AST::CollExpr
#result.push *val
@@ -1076,8 +1089,8 @@ module_eval <<'.,.,', 'grammar.ra', 239
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 244
- def _reduce_52( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 245
+ def _reduce_53( val, _values, result )
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
#result = ast AST::CollExpr
#result.push *val
@@ -1085,21 +1098,21 @@ module_eval <<'.,.,', 'grammar.ra', 244
end
.,.,
- # reduce 53 omitted
-
# reduce 54 omitted
-module_eval <<'.,.,', 'grammar.ra', 251
- def _reduce_55( val, _values, result )
+ # reduce 55 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 252
+ def _reduce_56( val, _values, result )
result = ast AST::ResourceInstance, :children => [val[0],val[2]]
result
end
.,.,
- # reduce 56 omitted
+ # reduce 57 omitted
-module_eval <<'.,.,', 'grammar.ra', 261
- def _reduce_57( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 262
+ def _reduce_58( val, _values, result )
if val[0].instance_of?(AST::ResourceInstance)
result = ast AST::ASTArray, :children => [val[0],val[2]]
else
@@ -1110,33 +1123,31 @@ module_eval <<'.,.,', 'grammar.ra', 261
end
.,.,
- # reduce 58 omitted
-
# reduce 59 omitted
-module_eval <<'.,.,', 'grammar.ra', 268
- def _reduce_60( val, _values, result )
+ # reduce 60 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 269
+ def _reduce_61( val, _values, result )
result = ast AST::Undef, :value => :undef
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 272
- def _reduce_61( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 273
+ def _reduce_62( val, _values, result )
result = ast AST::Name, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 276
- def _reduce_62( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 277
+ def _reduce_63( val, _values, result )
result = ast AST::Type, :value => val[0]
result
end
.,.,
- # reduce 63 omitted
-
# reduce 64 omitted
# reduce 65 omitted
@@ -1147,8 +1158,10 @@ module_eval <<'.,.,', 'grammar.ra', 276
# reduce 68 omitted
-module_eval <<'.,.,', 'grammar.ra', 292
- def _reduce_69( val, _values, result )
+ # reduce 69 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 293
+ def _reduce_70( val, _values, result )
if val[0] =~ /::/
raise Puppet::ParseError, "Cannot assign to variables in other namespaces"
end
@@ -1159,22 +1172,30 @@ module_eval <<'.,.,', 'grammar.ra', 292
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 297
- def _reduce_70( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 298
+ def _reduce_71( val, _values, result )
+ variable = ast AST::Name, :value => val[0]
+ result = ast AST::VarDef, :name => variable, :value => val[2], :append => true
+ result
+ end
+.,.,
+
+module_eval <<'.,.,', 'grammar.ra', 303
+ def _reduce_72( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 297
- def _reduce_71( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 303
+ def _reduce_73( val, _values, result )
result = val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 306
- def _reduce_72( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 312
+ def _reduce_74( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1185,41 +1206,41 @@ module_eval <<'.,.,', 'grammar.ra', 306
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 310
- def _reduce_73( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 316
+ def _reduce_75( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 315
- def _reduce_74( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 321
+ def _reduce_76( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2],
:add => true
result
end
.,.,
- # reduce 75 omitted
+ # reduce 77 omitted
- # reduce 76 omitted
+ # reduce 78 omitted
-module_eval <<'.,.,', 'grammar.ra', 323
- def _reduce_77( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 329
+ def _reduce_79( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 323
- def _reduce_78( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 329
+ def _reduce_80( val, _values, result )
result = val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 332
- def _reduce_79( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 338
+ def _reduce_81( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1230,10 +1251,10 @@ module_eval <<'.,.,', 'grammar.ra', 332
end
.,.,
- # reduce 80 omitted
+ # reduce 82 omitted
-module_eval <<'.,.,', 'grammar.ra', 341
- def _reduce_81( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 347
+ def _reduce_83( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
result = val[0].push(val[2])
else
@@ -1243,10 +1264,6 @@ module_eval <<'.,.,', 'grammar.ra', 341
end
.,.,
- # reduce 82 omitted
-
- # reduce 83 omitted
-
# reduce 84 omitted
# reduce 85 omitted
@@ -1275,8 +1292,12 @@ module_eval <<'.,.,', 'grammar.ra', 341
# reduce 97 omitted
-module_eval <<'.,.,', 'grammar.ra', 368
- def _reduce_98( val, _values, result )
+ # reduce 98 omitted
+
+ # reduce 99 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 374
+ def _reduce_100( val, _values, result )
args = aryfy(val[2])
result = ast AST::Function,
:name => val[0],
@@ -1286,8 +1307,8 @@ module_eval <<'.,.,', 'grammar.ra', 368
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 373
- def _reduce_99( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 379
+ def _reduce_101( val, _values, result )
result = ast AST::Function,
:name => val[0],
:arguments => AST::ASTArray.new({}),
@@ -1296,44 +1317,44 @@ module_eval <<'.,.,', 'grammar.ra', 373
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 377
- def _reduce_100( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 383
+ def _reduce_102( val, _values, result )
result = ast AST::String, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 379
- def _reduce_101( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 385
+ def _reduce_103( val, _values, result )
result = ast AST::FlatString, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 383
- def _reduce_102( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 389
+ def _reduce_104( val, _values, result )
result = ast AST::Boolean, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 388
- def _reduce_103( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 394
+ 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]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 390
- def _reduce_104( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 396
+ def _reduce_106( val, _values, result )
result = ast AST::ResourceReference, :type => val[0], :title => val[2]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 403
- def _reduce_105( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 409
+ def _reduce_107( val, _values, result )
args = {
:test => val[1],
:statements => val[3]
@@ -1348,19 +1369,19 @@ module_eval <<'.,.,', 'grammar.ra', 403
end
.,.,
- # reduce 106 omitted
+ # reduce 108 omitted
-module_eval <<'.,.,', 'grammar.ra', 408
- def _reduce_107( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 414
+ def _reduce_109( val, _values, result )
result = ast AST::Else, :statements => val[2]
result
end
.,.,
- # reduce 108 omitted
+ # reduce 110 omitted
-module_eval <<'.,.,', 'grammar.ra', 420
- def _reduce_109( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 426
+ def _reduce_111( val, _values, result )
options = val[3]
unless options.instance_of?(AST::ASTArray)
options = ast AST::ASTArray, :children => [val[3]]
@@ -1370,10 +1391,10 @@ module_eval <<'.,.,', 'grammar.ra', 420
end
.,.,
- # reduce 110 omitted
+ # reduce 112 omitted
-module_eval <<'.,.,', 'grammar.ra', 430
- def _reduce_111( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 436
+ def _reduce_113( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push val[1]
result = val[0]
@@ -1384,15 +1405,15 @@ module_eval <<'.,.,', 'grammar.ra', 430
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 434
- def _reduce_112( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 440
+ def _reduce_114( val, _values, result )
result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 439
- def _reduce_113( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 445
+ def _reduce_115( val, _values, result )
result = ast(AST::CaseOpt,
:value => val[0],
:statements => ast(AST::ASTArray)
@@ -1401,10 +1422,10 @@ module_eval <<'.,.,', 'grammar.ra', 439
end
.,.,
- # reduce 114 omitted
+ # reduce 116 omitted
-module_eval <<'.,.,', 'grammar.ra', 449
- def _reduce_115( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 455
+ def _reduce_117( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1415,26 +1436,26 @@ module_eval <<'.,.,', 'grammar.ra', 449
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 453
- def _reduce_116( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 459
+ def _reduce_118( val, _values, result )
result = ast AST::Selector, :param => val[0], :values => val[2]
result
end
.,.,
- # reduce 117 omitted
+ # reduce 119 omitted
-module_eval <<'.,.,', 'grammar.ra', 455
- def _reduce_118( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 461
+ def _reduce_120( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 119 omitted
+ # reduce 121 omitted
-module_eval <<'.,.,', 'grammar.ra', 466
- def _reduce_120( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 472
+ def _reduce_122( val, _values, result )
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
@@ -1445,17 +1466,13 @@ module_eval <<'.,.,', 'grammar.ra', 466
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 470
- def _reduce_121( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 476
+ def _reduce_123( val, _values, result )
result = ast AST::ResourceParam, :param => val[0], :value => val[2]
result
end
.,.,
- # reduce 122 omitted
-
- # reduce 123 omitted
-
# reduce 124 omitted
# reduce 125 omitted
@@ -1466,29 +1483,33 @@ module_eval <<'.,.,', 'grammar.ra', 470
# reduce 128 omitted
-module_eval <<'.,.,', 'grammar.ra', 481
- def _reduce_129( val, _values, result )
+ # reduce 129 omitted
+
+ # reduce 130 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 487
+ def _reduce_131( val, _values, result )
result = ast AST::Default, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 483
- def _reduce_130( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 489
+ def _reduce_132( val, _values, result )
result = [val[0].value]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 487
- def _reduce_131( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 493
+ def _reduce_133( val, _values, result )
results = val[0] << val[2].value
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 495
- def _reduce_132( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 501
+ def _reduce_134( val, _values, result )
val[1].each do |file|
import(file)
end
@@ -1498,8 +1519,8 @@ module_eval <<'.,.,', 'grammar.ra', 495
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 505
- def _reduce_133( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 511
+ def _reduce_135( val, _values, result )
newdefine classname(val[1]), :arguments => val[2], :code => val[4]
@lexer.indefine = false
result = nil
@@ -1509,8 +1530,8 @@ module_eval <<'.,.,', 'grammar.ra', 505
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 509
- def _reduce_134( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 515
+ def _reduce_136( val, _values, result )
newdefine classname(val[1]), :arguments => val[2]
@lexer.indefine = false
result = nil
@@ -1518,8 +1539,8 @@ module_eval <<'.,.,', 'grammar.ra', 509
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 517
- def _reduce_135( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 523
+ def _reduce_137( 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]
@@ -1528,8 +1549,8 @@ module_eval <<'.,.,', 'grammar.ra', 517
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 522
- def _reduce_136( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 528
+ def _reduce_138( val, _values, result )
# Our class gets defined in the parent namespace, not our own.
@lexer.namepop
newclass classname(val[1]), :parent => val[2]
@@ -1538,32 +1559,32 @@ module_eval <<'.,.,', 'grammar.ra', 522
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 527
- def _reduce_137( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 533
+ def _reduce_139( val, _values, result )
newnode val[1], :parent => val[2], :code => val[4]
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 530
- def _reduce_138( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 536
+ def _reduce_140( val, _values, result )
newnode val[1], :parent => val[2]
result = nil
result
end
.,.,
- # reduce 139 omitted
-
- # reduce 140 omitted
-
# reduce 141 omitted
# reduce 142 omitted
-module_eval <<'.,.,', 'grammar.ra', 544
- def _reduce_143( val, _values, result )
+ # reduce 143 omitted
+
+ # reduce 144 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 550
+ def _reduce_145( val, _values, result )
result = val[0]
result = [result] unless result.is_a?(Array)
result << val[2]
@@ -1571,49 +1592,49 @@ module_eval <<'.,.,', 'grammar.ra', 544
end
.,.,
- # reduce 144 omitted
-
- # reduce 145 omitted
-
# reduce 146 omitted
# reduce 147 omitted
-module_eval <<'.,.,', 'grammar.ra', 553
- def _reduce_148( val, _values, result )
+ # reduce 148 omitted
+
+ # reduce 149 omitted
+
+module_eval <<'.,.,', 'grammar.ra', 559
+ def _reduce_150( val, _values, result )
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 557
- def _reduce_149( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 563
+ def _reduce_151( val, _values, result )
result = ast AST::ASTArray, :children => []
result
end
.,.,
- # reduce 150 omitted
+ # reduce 152 omitted
-module_eval <<'.,.,', 'grammar.ra', 562
- def _reduce_151( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 568
+ def _reduce_153( val, _values, result )
result = nil
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 566
- def _reduce_152( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 572
+ def _reduce_154( val, _values, result )
result = val[1]
result = [result] unless result[0].is_a?(Array)
result
end
.,.,
- # reduce 153 omitted
+ # reduce 155 omitted
-module_eval <<'.,.,', 'grammar.ra', 573
- def _reduce_154( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 579
+ def _reduce_156( val, _values, result )
result = val[0]
result = [result] unless result[0].is_a?(Array)
result << val[2]
@@ -1621,67 +1642,67 @@ module_eval <<'.,.,', 'grammar.ra', 573
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 578
- def _reduce_155( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 584
+ def _reduce_157( val, _values, result )
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0], val[2]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 582
- def _reduce_156( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 588
+ def _reduce_158( val, _values, result )
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 584
- def _reduce_157( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 590
+ def _reduce_159( val, _values, result )
result = [val[0], val[2]]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 586
- def _reduce_158( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 592
+ def _reduce_160( val, _values, result )
result = [val[0]]
result
end
.,.,
- # reduce 159 omitted
+ # reduce 161 omitted
-module_eval <<'.,.,', 'grammar.ra', 591
- def _reduce_160( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 597
+ def _reduce_162( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 161 omitted
+ # reduce 163 omitted
-module_eval <<'.,.,', 'grammar.ra', 596
- def _reduce_162( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 602
+ def _reduce_164( val, _values, result )
result = val[1]
result
end
.,.,
- # reduce 163 omitted
+ # reduce 165 omitted
- # reduce 164 omitted
+ # reduce 166 omitted
-module_eval <<'.,.,', 'grammar.ra', 602
- def _reduce_165( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 608
+ def _reduce_167( val, _values, result )
result = ast AST::Variable, :value => val[0]
result
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 610
- def _reduce_166( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 616
+ def _reduce_168( val, _values, result )
if val[1].instance_of?(AST::ASTArray)
result = val[1]
else
@@ -1691,21 +1712,21 @@ module_eval <<'.,.,', 'grammar.ra', 610
end
.,.,
-module_eval <<'.,.,', 'grammar.ra', 612
- def _reduce_167( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 618
+ def _reduce_169( val, _values, result )
result = ast AST::ASTArray
result
end
.,.,
- # reduce 168 omitted
+ # reduce 170 omitted
- # reduce 169 omitted
+ # reduce 171 omitted
- # reduce 170 omitted
+ # reduce 172 omitted
-module_eval <<'.,.,', 'grammar.ra', 617
- def _reduce_171( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 623
+ def _reduce_173( val, _values, result )
result = nil
result
end
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 32b127a6b..1ff998d96 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -260,11 +260,15 @@ class Puppet::Parser::Scope
# Set a variable in the current scope. This will override settings
# in scopes above, but will not allow variables in the current scope
# to be reassigned.
- def setvar(name,value, file = nil, line = nil)
- #Puppet.debug "Setting %s to '%s' at level %s" %
- # [name.inspect,value,self.level]
+ def setvar(name,value, file = nil, line = nil, append = false)
+ #Puppet.debug "Setting %s to '%s' at level %s mode append %s" %
+ # [name.inspect,value,self.level, append]
if @symtable.include?(name)
- error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
+ unless append
+ error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
+ else
+ error = Puppet::ParseError.new("Cannot append, variable %s is defined in this scope" % name)
+ end
if file
error.file = file
end
@@ -273,7 +277,19 @@ class Puppet::Parser::Scope
end
raise error
end
- @symtable[name] = value
+
+ unless append
+ @symtable[name] = value
+ else # append case
+ # lookup the value in the scope if it exists and insert the var
+ @symtable[name] = lookupvar(name)
+ # concatenate if string, append if array, nothing for other types
+ if value.is_a?(Array)
+ @symtable[name] += value
+ else
+ @symtable[name] << value
+ end
+ end
end
# Return an interpolated string.
diff --git a/lib/puppet/property.rb b/lib/puppet/property.rb
index 9e8bae7a4..50a1b71de 100644
--- a/lib/puppet/property.rb
+++ b/lib/puppet/property.rb
@@ -441,7 +441,13 @@ class Property < Puppet::Parameter
return "%s(%s)" % [@resource.name,self.name]
end
- # Provide a common hook for setting @should, just like params.
+ # Just return any should value we might have.
+ def value
+ self.should
+ end
+
+ # Match the Parameter interface, but we really just use 'should' internally.
+ # Note that the should= method does all of the validation and such.
def value=(value)
self.should = value
end
diff --git a/lib/puppet/provider/package/appdmg.rb b/lib/puppet/provider/package/appdmg.rb
index e822be14c..2ee82a95d 100644
--- a/lib/puppet/provider/package/appdmg.rb
+++ b/lib/puppet/provider/package/appdmg.rb
@@ -55,7 +55,7 @@ Puppet::Type.type(:package).provide(:appdmg, :parent => Puppet::Provider::Packag
self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
end
require 'open-uri'
- require 'puppet/util/plist'
+ require 'facter/util/plist'
cached_source = source
if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
cached_source = "/tmp/#{name}"
diff --git a/lib/puppet/provider/package/pkgdmg.rb b/lib/puppet/provider/package/pkgdmg.rb
index 134be5a65..fa546c61f 100644
--- a/lib/puppet/provider/package/pkgdmg.rb
+++ b/lib/puppet/provider/package/pkgdmg.rb
@@ -70,7 +70,7 @@ Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Packag
self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
end
require 'open-uri'
- require 'puppet/util/plist'
+ require 'facter/util/plist'
cached_source = source
if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
cached_source = "/tmp/#{name}"
diff --git a/lib/puppet/provider/service/daemontools.rb b/lib/puppet/provider/service/daemontools.rb
new file mode 100644
index 000000000..52d8c6b6c
--- /dev/null
+++ b/lib/puppet/provider/service/daemontools.rb
@@ -0,0 +1,154 @@
+# Daemontools service management
+#
+# author Brice Figureau <brice-puppet@daysofwonder.com>
+Puppet::Type.type(:service).provide :daemontools, :parent => :base do
+ desc "Daemontools service management.
+ This provider manages daemons running supervised by D.J.Bernstein daemontools.
+ It tries to detect the service directory, with by order of preference:
+ * /service
+ * /etc/service
+ * /var/lib/svscan
+ The daemon directory should be placed in a directory that can be
+ by default in:
+ * /var/lib/service
+ * /etc
+ or this can be overriden in the service resource parameters:
+ service {
+ \"myservice\":
+ provider => \"daemontools\", path => \"/path/to/daemons\";
+ }
+
+ This provider supports out of the box:
+ * start/stop (mapped to enable/disable)
+ * enable/disable
+ * restart
+ * status"
+
+ commands :svc => "/usr/bin/svc"
+ commands :svstat => "/usr/bin/svstat"
+
+ class << self
+ attr_writer :defpath
+
+ # this is necessary to autodetect a valid resource
+ # default path, since there is no standard for such directory.
+ def defpath
+ unless defined?(@defpath) and @defpath
+ ["/var/lib/service", "/etc"].each do |path|
+ if FileTest.exist?(path)
+ @defpath = path
+ break
+ end
+ end
+ raise "Could not find the daemon directory (tested [/var/lib/service,/etc])" unless @defpath
+ end
+ @defpath
+ end
+ end
+
+ attr_writer :servicedir
+
+ # returns all providers for all existing services in @defpath
+ # ie enabled or not
+ def self.instances
+ path = self.defpath
+ unless FileTest.directory?(path)
+ Puppet.notice "Service path %s does not exist" % path
+ next
+ end
+
+ # reject entries that aren't either a directory
+ # or don't contain a run file
+ Dir.entries(path).reject { |e|
+ fullpath = File.join(path, e)
+ e =~ /^\./ or ! FileTest.directory?(fullpath) or ! FileTest.exist?(File.join(fullpath,"run"))
+ }.collect do |name|
+ new(:name => name, :path => path)
+ end
+ end
+
+ # returns the daemon dir on this node
+ def self.daemondir
+ self.defpath
+ end
+
+ # find the service dir on this node
+ def servicedir
+ unless defined?(@servicedir) and @servicedir
+ ["/service", "/etc/service","/var/lib/svscan"].each do |path|
+ if FileTest.exist?(path)
+ @servicedir = path
+ break
+ end
+ end
+ raise "Could not find service directory" unless @servicedir
+ end
+ @servicedir
+ end
+
+ # returns the full path of this service when enabled
+ # (ie in the service directory)
+ def service
+ File.join(self.servicedir, resource[:name])
+ end
+
+ # returns the full path to the current daemon directory
+ # note that this path can be overriden in the resource
+ # definition
+ def daemon
+ File.join(resource[:path], resource[:name])
+ end
+
+ def restartcmd
+ [ command(:svc), "-t", self.service]
+ end
+
+ # The start command does nothing, service are automatically started
+ # when enabled by svscan. But, forces an enable if necessary
+ def start
+ # to start make sure the sevice is enabled
+ self.enable
+ # start is then automatic
+ end
+
+ def status
+ begin
+ output = svstat self.service
+ return :running if output =~ /\bup\b/
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error.new( "Could not get status for service %s: %s" % [ resource.ref, detail] )
+ end
+ return :stopped
+ end
+
+ # unfortunately it is not possible
+ # to stop without disabling the service
+ def stop
+ self.disable
+ end
+
+ # disable by stopping the service
+ # and removing the symlink so that svscan
+ # doesn't restart our service behind our back
+ def disable
+ # should stop the service
+ # stop the log subservice if any
+ log = File.join(self.service, "log")
+ texecute("stop log", [ command(:svc) , '-dx', log] ) if FileTest.directory?(log)
+
+ # stop the main resource
+ texecute("stop", [command(:svc), '-dx', self.service] )
+
+ # unlink the daemon symlink to disable it
+ File.unlink(self.service) if FileTest.symlink?(self.service)
+ end
+
+ def enabled?
+ FileTest.symlink?(self.service)
+ end
+
+ def enable
+ File.symlink(self.daemon, self.service) if ! FileTest.symlink?(self.service)
+ end
+end
+
diff --git a/lib/puppet/provider/service/runit.rb b/lib/puppet/provider/service/runit.rb
new file mode 100644
index 000000000..230fa75d9
--- /dev/null
+++ b/lib/puppet/provider/service/runit.rb
@@ -0,0 +1,93 @@
+# Daemontools service management
+#
+# author Brice Figureau <brice-puppet@daysofwonder.com>
+Puppet::Type.type(:service).provide :runit, :parent => :daemontools do
+ desc "Runit service management.
+ This provider manages daemons running supervised by Runit.
+ It tries to detect the service directory, with by order of preference:
+ * /service
+ * /var/service
+ * /etc/service
+ The daemon directory should be placed in a directory that can be
+ by default in:
+ * /etc/sv
+ or this can be overriden in the service resource parameters:
+ service {
+ \"myservice\":
+ provider => \"runit\", path => \"/path/to/daemons\";
+ }
+
+ This provider supports out of the box:
+ * start/stop
+ * enable/disable
+ * restart
+ * status"
+
+ commands :sv => "/usr/bin/sv"
+
+ class << self
+ # this is necessary to autodetect a valid resource
+ # default path, since there is no standard for such directory.
+ def defpath
+ unless defined?(@defpath) and @defpath
+ ["/etc/sv", "/var/lib/service"].each do |path|
+ if FileTest.exist?(path)
+ @defpath = path
+ break
+ end
+ end
+ raise "Could not find the daemon directory (tested [/var/lib/service,/etc])" unless @defpath
+ end
+ @defpath
+ end
+ end
+
+ # find the service dir on this node
+ def servicedir
+ unless defined?(@servicedir) and @servicedir
+ ["/service", "/etc/service","/var/service"].each do |path|
+ if FileTest.exist?(path)
+ @servicedir = path
+ break
+ end
+ end
+ raise "Could not find service directory" unless @servicedir
+ end
+ @servicedir
+ end
+
+ def restartcmd
+ [ command(:sv), "restart", self.service]
+ end
+
+ def status
+ begin
+ output = sv "status", self.daemon
+ return :running if output =~ /^run: /
+ rescue Puppet::ExecutionFailure => detail
+ unless detail.message =~ /(warning: |runsv not running$)/
+ raise Puppet::Error.new( "Could not get status for service %s: %s" % [ resource.ref, detail] )
+ end
+ end
+ return :stopped
+ end
+
+ # relay to the stopcmd
+ def stop
+ ucommand( :stop )
+ end
+
+ def stopcmd
+ [ command(:sv), "stop", self.service]
+ end
+
+ # disable by removing the symlink so that runit
+ # doesn't restart our service behind our back
+ # note that runit doesn't need to perform a stop
+ # before a disable
+ def disable
+ # unlink the daemon symlink to disable it
+ File.unlink(self.service) if FileTest.symlink?(self.service)
+ end
+end
+
diff --git a/lib/puppet/provider/user/hpux.rb b/lib/puppet/provider/user/hpux.rb
new file mode 100644
index 000000000..672b77da6
--- /dev/null
+++ b/lib/puppet/provider/user/hpux.rb
@@ -0,0 +1,30 @@
+Puppet::Type.type(:user).provide :hpuxuseradd, :parent => :useradd do
+ desc "User management for hp-ux! Undocumented switch to special usermod because HP-UX regular usermod is TOO STUPID to change stuff while the user is logged in."
+
+ defaultfor :operatingsystem => "hp-ux"
+ confine :operatingsystem => "hp-ux"
+
+ commands :modify => "/usr/sam/lbin/usermod.sam", :delete => "/usr/sam/lbin/userdel.sam", :add => "/usr/sbin/useradd"
+ options :comment, :method => :gecos
+ options :groups, :flag => "-G"
+ options :home, :flag => "-d", :method => :dir
+
+ 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
+
+ def deletecmd
+ super.insert(1,"-F")
+ end
+
+ def modifycmd(param,value)
+ super.insert(1,"-F")
+ end
+
+end
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index a6aff152c..11e8c8248 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -20,20 +20,2089 @@ class Type
include Puppet::Util::LogPaths
include Puppet::Util::Logging
- # Nearly all of the code in this class is stored in files in the
- # metatype/ directory. This is a temporary measure until I get a chance
- # to refactor this class entirely. There's still more simplification to
- # do, but this works for now.
- require 'puppet/metatype/attributes'
- require 'puppet/metatype/closure'
- require 'puppet/metatype/container'
- require 'puppet/metatype/evaluation'
- require 'puppet/metatype/instances'
- require 'puppet/metatype/metaparams'
- require 'puppet/metatype/providers'
- require 'puppet/metatype/relationships'
- require 'puppet/metatype/schedules'
- require 'puppet/metatype/tags'
+ ###############################
+ # Code related to resource type attributes.
+ class << self
+ include Puppet::Util::ClassGen
+ include Puppet::Util::Warnings
+ attr_reader :properties
+ end
+
+ def self.states
+ warnonce "The states method is deprecated; use properties"
+ properties()
+ end
+
+ # All parameters, in the appropriate order. The namevar comes first,
+ # then the properties, then the params and metaparams in the order they
+ # were specified in the files.
+ def self.allattrs
+ # now get all of the arguments, in a specific order
+ # Cache this, since it gets called so many times
+ namevar = self.namevar
+
+ order = [namevar]
+ if self.parameters.include?(:provider)
+ order << :provider
+ end
+ order << [self.properties.collect { |property| property.name },
+ self.parameters - [:provider],
+ self.metaparams].flatten.reject { |param|
+ # we don't want our namevar in there multiple times
+ param == namevar
+ }
+
+ order.flatten!
+
+ return order
+ end
+
+ # Retrieve an attribute alias, if there is one.
+ def self.attr_alias(param)
+ @attr_aliases[symbolize(param)]
+ end
+
+ # Create an alias to an existing attribute. This will cause the aliased
+ # attribute to be valid when setting and retrieving values on the instance.
+ def self.set_attr_alias(hash)
+ hash.each do |new, old|
+ @attr_aliases[symbolize(new)] = symbolize(old)
+ end
+ end
+
+ # Find the class associated with any given attribute.
+ def self.attrclass(name)
+ @attrclasses ||= {}
+
+ # We cache the value, since this method gets called such a huge number
+ # of times (as in, hundreds of thousands in a given run).
+ unless @attrclasses.include?(name)
+ @attrclasses[name] = case self.attrtype(name)
+ when :property: @validproperties[name]
+ when :meta: @@metaparamhash[name]
+ when :param: @paramhash[name]
+ end
+ end
+ @attrclasses[name]
+ end
+
+ # What type of parameter are we dealing with? Cache the results, because
+ # this method gets called so many times.
+ def self.attrtype(attr)
+ @attrtypes ||= {}
+ unless @attrtypes.include?(attr)
+ @attrtypes[attr] = case
+ when @validproperties.include?(attr): :property
+ when @paramhash.include?(attr): :param
+ when @@metaparamhash.include?(attr): :meta
+ else
+ raise Puppet::DevError,
+ "Invalid attribute '%s' for class '%s'" %
+ [attr, self.name]
+ end
+ end
+
+ @attrtypes[attr]
+ end
+
+ # Copy an existing class parameter. This allows other types to avoid
+ # duplicating a parameter definition, and is mostly used by subclasses
+ # of the File class.
+ def self.copyparam(klass, name)
+ param = klass.attrclass(name)
+
+ unless param
+ raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
+ end
+ @parameters << param
+ @parameters.each { |p| @paramhash[name] = p }
+
+ if param.isnamevar?
+ @namevar = param.name
+ end
+ end
+
+ # A similar function but one that yields the class and type.
+ # This is mainly so that setdefaults doesn't call quite so many functions.
+ def self.eachattr(*ary)
+ if ary.empty?
+ ary = nil
+ end
+
+ # We have to do this in a specific order, so that defaults are
+ # created in that order (e.g., providers should be set up before
+ # anything else).
+ allattrs.each do |name|
+ next unless ary.nil? or ary.include?(name)
+ if obj = @properties.find { |p| p.name == name }
+ yield obj, :property
+ elsif obj = @parameters.find { |p| p.name == name }
+ yield obj, :param
+ elsif obj = @@metaparams.find { |p| p.name == name }
+ yield obj, :meta
+ else
+ raise Puppet::DevError, "Could not find parameter %s" % name
+ end
+ end
+ end
+
+ def self.eachmetaparam
+ @@metaparams.each { |p| yield p.name }
+ end
+
+ # Create the 'ensure' class. This is a separate method so other types
+ # can easily call it and create their own 'ensure' values.
+ def self.ensurable(&block)
+ if block_given?
+ self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block)
+ else
+ self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do
+ self.defaultvalues
+ end
+ end
+ end
+
+ # Should we add the 'ensure' property to this class?
+ def self.ensurable?
+ # If the class has all three of these methods defined, then it's
+ # ensurable.
+ ens = [:exists?, :create, :destroy].inject { |set, method|
+ set &&= self.public_method_defined?(method)
+ }
+
+ return ens
+ end
+
+ # Deal with any options passed into parameters.
+ def self.handle_param_options(name, options)
+ # If it's a boolean parameter, create a method to test the value easily
+ if options[:boolean]
+ define_method(name.to_s + "?") do
+ val = self[name]
+ if val == :true or val == true
+ return true
+ end
+ end
+ end
+
+ # If this param handles relationships, store that information
+ end
+
+ # Is the parameter in question a meta-parameter?
+ def self.metaparam?(param)
+ @@metaparamhash.include?(symbolize(param))
+ end
+
+ # Find the metaparameter class associated with a given metaparameter name.
+ def self.metaparamclass(name)
+ @@metaparamhash[symbolize(name)]
+ end
+
+ def self.metaparams
+ @@metaparams.collect { |param| param.name }
+ end
+
+ def self.metaparamdoc(metaparam)
+ @@metaparamhash[metaparam].doc
+ end
+
+ # Create a new metaparam. Requires a block and a name, stores it in the
+ # @parameters array, and does some basic checking on it.
+ def self.newmetaparam(name, options = {}, &block)
+ @@metaparams ||= []
+ @@metaparamhash ||= {}
+ name = symbolize(name)
+
+ param = genclass(name,
+ :parent => options[:parent] || Puppet::Parameter,
+ :prefix => "MetaParam",
+ :hash => @@metaparamhash,
+ :array => @@metaparams,
+ :attributes => options[:attributes],
+ &block
+ )
+
+ # Grr.
+ if options[:required_features]
+ param.required_features = options[:required_features]
+ end
+
+ handle_param_options(name, options)
+
+ param.metaparam = true
+
+ return param
+ end
+
+ # Find the namevar
+ def self.namevar
+ unless defined? @namevar
+ params = @parameters.find_all { |param|
+ param.isnamevar? or param.name == :name
+ }
+
+ if params.length > 1
+ raise Puppet::DevError, "Found multiple namevars for %s" % self.name
+ elsif params.length == 1
+ @namevar = params[0].name
+ else
+ raise Puppet::DevError, "No namevar for %s" % self.name
+ end
+ end
+ @namevar
+ end
+
+ # Create a new parameter. Requires a block and a name, stores it in the
+ # @parameters array, and does some basic checking on it.
+ def self.newparam(name, options = {}, &block)
+ options[:attributes] ||= {}
+ param = genclass(name,
+ :parent => options[:parent] || Puppet::Parameter,
+ :attributes => options[:attributes],
+ :block => block,
+ :prefix => "Parameter",
+ :array => @parameters,
+ :hash => @paramhash
+ )
+
+ handle_param_options(name, options)
+
+ # Grr.
+ if options[:required_features]
+ param.required_features = options[:required_features]
+ end
+
+ param.isnamevar if options[:namevar]
+
+ # These might be enabled later.
+# define_method(name) do
+# @parameters[name].value
+# end
+#
+# define_method(name.to_s + "=") do |value|
+# newparam(param, value)
+# end
+
+ if param.isnamevar?
+ @namevar = param.name
+ end
+
+ return param
+ end
+
+ def self.newstate(name, options = {}, &block)
+ Puppet.warning "newstate() has been deprecrated; use newproperty(%s)" %
+ name
+ newproperty(name, options, &block)
+ end
+
+ # Create a new property. The first parameter must be the name of the property;
+ # this is how users will refer to the property when creating new instances.
+ # The second parameter is a hash of options; the options are:
+ # * <tt>:parent</tt>: The parent class for the property. Defaults to Puppet::Property.
+ # * <tt>:retrieve</tt>: The method to call on the provider or @parent object (if
+ # the provider is not set) to retrieve the current value.
+ def self.newproperty(name, options = {}, &block)
+ name = symbolize(name)
+
+ # This is here for types that might still have the old method of defining
+ # a parent class.
+ unless options.is_a? Hash
+ raise Puppet::DevError,
+ "Options must be a hash, not %s" % options.inspect
+ end
+
+ if @validproperties.include?(name)
+ raise Puppet::DevError, "Class %s already has a property named %s" %
+ [self.name, name]
+ end
+
+ if parent = options[:parent]
+ options.delete(:parent)
+ else
+ parent = Puppet::Property
+ end
+
+ # We have to create our own, new block here because we want to define
+ # an initial :retrieve method, if told to, and then eval the passed
+ # block if available.
+ prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do
+ # If they've passed a retrieve method, then override the retrieve
+ # method on the class.
+ if options[:retrieve]
+ define_method(:retrieve) do
+ provider.send(options[:retrieve])
+ end
+ end
+
+ if block
+ class_eval(&block)
+ end
+ end
+
+ # If it's the 'ensure' property, always put it first.
+ if name == :ensure
+ @properties.unshift prop
+ else
+ @properties << prop
+ end
+
+# define_method(name) do
+# @parameters[name].should
+# end
+#
+# define_method(name.to_s + "=") do |value|
+# newproperty(name, :should => value)
+# end
+
+ return prop
+ end
+
+ def self.paramdoc(param)
+ @paramhash[param].doc
+ end
+
+ # Return the parameter names
+ def self.parameters
+ return [] unless defined? @parameters
+ @parameters.collect { |klass| klass.name }
+ end
+
+ # Find the parameter class associated with a given parameter name.
+ def self.paramclass(name)
+ @paramhash[name]
+ end
+
+ # Return the property class associated with a name
+ def self.propertybyname(name)
+ @validproperties[name]
+ end
+
+ def self.validattr?(name)
+ name = symbolize(name)
+ return true if name == :name
+ @validattrs ||= {}
+
+ unless @validattrs.include?(name)
+ if self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)
+ @validattrs[name] = true
+ else
+ @validattrs[name] = false
+ end
+ end
+
+ @validattrs[name]
+ end
+
+ # does the name reflect a valid property?
+ def self.validproperty?(name)
+ name = symbolize(name)
+ if @validproperties.include?(name)
+ return @validproperties[name]
+ else
+ return false
+ end
+ end
+
+ # Return the list of validproperties
+ def self.validproperties
+ return {} unless defined? @parameters
+
+ return @validproperties.keys
+ end
+
+ # does the name reflect a valid parameter?
+ def self.validparameter?(name)
+ unless defined? @parameters
+ raise Puppet::DevError, "Class %s has not defined parameters" % self
+ end
+ if @paramhash.include?(name) or @@metaparamhash.include?(name)
+ return true
+ else
+ return false
+ end
+ end
+
+ # fix any namevar => param translations
+ def argclean(oldhash)
+ # This duplication is here because it might be a transobject.
+ hash = oldhash.dup.to_hash
+
+ if hash.include?(:resource)
+ hash.delete(:resource)
+ end
+ namevar = self.class.namevar
+
+ # Do a simple translation for those cases where they've passed :name
+ # but that's not our namevar
+ if hash.include? :name and namevar != :name
+ if hash.include? namevar
+ raise ArgumentError, "Cannot provide both name and %s" % namevar
+ end
+ hash[namevar] = hash[:name]
+ hash.delete(:name)
+ end
+
+ # Make sure we have a name, one way or another
+ unless hash.include? namevar
+ if defined? @title and @title
+ hash[namevar] = @title
+ else
+ raise Puppet::Error, "Was not passed a namevar or title"
+ end
+ end
+
+ return hash
+ end
+
+ # Return either the attribute alias or the attribute.
+ def attr_alias(name)
+ name = symbolize(name)
+ if synonym = self.class.attr_alias(name)
+ return synonym
+ else
+ return name
+ end
+ end
+
+ # Are we deleting this resource?
+ def deleting?
+ obj = @parameters[:ensure] and obj.should == :absent
+ end
+
+ # Create a new property if it is valid but doesn't exist
+ # Returns: true if a new parameter was added, false otherwise
+ def add_property_parameter(prop_name)
+ if self.class.validproperty?(prop_name) && !@parameters[prop_name]
+ self.newattr(prop_name)
+ return true
+ end
+ return false
+ end
+
+ # abstract accessing parameters and properties, and normalize
+ # access to always be symbols, not strings
+ # This returns a value, not an object. It returns the 'is'
+ # value, but you can also specifically return 'is' and 'should'
+ # values using 'object.is(:property)' or 'object.should(:property)'.
+ def [](name)
+ name = attr_alias(name)
+
+ unless self.class.validattr?(name)
+ raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
+ end
+
+ if name == :name
+ name = self.class.namevar
+ end
+
+ if obj = @parameters[name]
+ # Note that if this is a property, then the value is the "should" value,
+ # not the current value.
+ obj.value
+ else
+ return nil
+ end
+ end
+
+ # Abstract setting parameters and properties, and normalize
+ # access to always be symbols, not strings. This sets the 'should'
+ # value on properties, and otherwise just sets the appropriate parameter.
+ def []=(name,value)
+ name = attr_alias(name)
+
+ unless self.class.validattr?(name)
+ raise TypeError.new("Invalid parameter %s" % [name])
+ end
+
+ if name == :name
+ name = self.class.namevar
+ end
+ if value.nil?
+ raise Puppet::Error.new("Got nil value for %s" % name)
+ end
+
+ if obj = @parameters[name]
+ obj.value = value
+ return nil
+ else
+ self.newattr(name, :value => value)
+ end
+
+ nil
+ end
+
+ # remove a property from the object; useful in testing or in cleanup
+ # when an error has been encountered
+ def delete(attr)
+ attr = symbolize(attr)
+ if @parameters.has_key?(attr)
+ @parameters.delete(attr)
+ else
+ raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
+ end
+ end
+
+ # iterate across the existing properties
+ def eachproperty
+ # properties() is a private method
+ properties().each { |property|
+ yield property
+ }
+ end
+
+ # retrieve the 'should' value for a specified property
+ def should(name)
+ name = attr_alias(name)
+ if prop = @parameters[name] and prop.is_a?(Puppet::Property)
+ return prop.should
+ else
+ return nil
+ end
+ end
+
+ # Create the actual attribute instance. Requires either the attribute
+ # name or class as the first argument, then an optional hash of
+ # attributes to set during initialization.
+ def newattr(name, options = {})
+ if name.is_a?(Class)
+ klass = name
+ name = klass.name
+ end
+
+ unless klass = self.class.attrclass(name)
+ raise Puppet::Error, "Resource type %s does not support parameter %s" % [self.class.name, name]
+ end
+
+ if @parameters.include?(name)
+ raise Puppet::Error, "Parameter '%s' is already defined in %s" %
+ [name, self.ref]
+ end
+
+ if provider and ! provider.class.supports_parameter?(klass)
+ missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) }
+ info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name]
+ return nil
+ end
+
+ # Add resource information at creation time, so it's available
+ # during validation.
+ options[:resource] = self
+ begin
+ # make sure the parameter doesn't have any errors
+ return @parameters[name] = klass.new(options)
+ rescue => detail
+ error = Puppet::Error.new("Parameter %s failed: %s" %
+ [name, detail])
+ error.set_backtrace(detail.backtrace)
+ raise error
+ end
+ end
+
+ # return the value of a parameter
+ def parameter(name)
+ unless name.is_a? Symbol
+ name = name.intern
+ end
+ return @parameters[name].value
+ end
+
+ # Is the named property defined?
+ def propertydefined?(name)
+ unless name.is_a? Symbol
+ name = name.intern
+ end
+ return @parameters.include?(name)
+ end
+
+ # return an actual type by name; to return the value, use 'inst[name]'
+ # FIXME this method should go away
+ def property(name)
+ if obj = @parameters[symbolize(name)] and obj.is_a?(Puppet::Property)
+ return obj
+ else
+ return nil
+ end
+ end
+
+# def set(name, value)
+# send(name.to_s + "=", value)
+# end
+#
+# def get(name)
+# send(name)
+# end
+
+ # For any parameters or properties that have defaults and have not yet been
+ # set, set them now. This method can be handed a list of attributes,
+ # and if so it will only set defaults for those attributes.
+ def setdefaults(*ary)
+ #self.class.eachattr(*ary) { |klass, type|
+ self.class.eachattr(*ary) { |klass, type|
+ # not many attributes will have defaults defined, so we short-circuit
+ # those away
+ next unless klass.method_defined?(:default)
+ next if @parameters[klass.name]
+
+ next unless obj = self.newattr(klass)
+
+ # We have to check for nil values, not "truth", so we allow defaults
+ # to false.
+ value = obj.default and ! value.nil?
+ if ! value.nil?
+ obj.value = value
+ else
+ @parameters.delete(obj.name)
+ end
+ }
+ end
+
+ # Convert our object to a hash. This just includes properties.
+ def to_hash
+ rethash = {}
+
+ @parameters.each do |name, obj|
+ rethash[name] = obj.value
+ end
+
+ rethash
+ end
+
+ # Return a specific value for an attribute.
+ def value(name)
+ name = attr_alias(name)
+
+ if obj = @parameters[name] and obj.respond_to?(:value)
+ return obj.value
+ else
+ return nil
+ end
+ end
+
+ # Meta-parameter methods: These methods deal with the results
+ # of specifying metaparameters
+
+ private
+
+ # Return all of the property objects, in the order specified in the
+ # class.
+ def properties
+ #debug "%s has %s properties" % [self,@parameters.length]
+ props = self.class.properties.collect { |prop|
+ @parameters[prop.name]
+ }.find_all { |p|
+ ! p.nil?
+ }.each do |prop|
+ unless prop.is_a?(Puppet::Property)
+ raise Puppet::DevError, "got a non-property %s(%s)" %
+ [prop.class, prop.class.name]
+ end
+ end
+
+ props
+ end
+
+ public
+
+ ###############################
+ # Code related to the closure-like behaviour of the resource classes.
+ attr_writer :implicit
+
+ # Is this type's name isomorphic with the object? That is, if the
+ # name conflicts, does it necessarily mean that the objects conflict?
+ # Defaults to true.
+ def self.isomorphic?
+ if defined? @isomorphic
+ return @isomorphic
+ else
+ return true
+ end
+ end
+
+ def implicit?
+ if defined? @implicit and @implicit
+ return true
+ else
+ return false
+ end
+ end
+
+ def isomorphic?
+ self.class.isomorphic?
+ end
+
+ # is the instance a managed instance? A 'yes' here means that
+ # the instance was created from the language, vs. being created
+ # in order resolve other questions, such as finding a package
+ # in a list
+ def managed?
+ # Once an object is managed, it always stays managed; but an object
+ # that is listed as unmanaged might become managed later in the process,
+ # so we have to check that every time
+ if defined? @managed and @managed
+ return @managed
+ else
+ @managed = false
+ properties.each { |property|
+ s = property.should
+ if s and ! property.class.unmanaged
+ @managed = true
+ break
+ end
+ }
+ return @managed
+ end
+ end
+
+ ###############################
+ # Code related to the container behaviour.
+
+ # this is a retarded hack method to get around the difference between
+ # component children and file children
+ def self.depthfirst?
+ if defined? @depthfirst
+ return @depthfirst
+ else
+ return false
+ end
+ end
+
+ def depthfirst?
+ self.class.depthfirst?
+ end
+
+ # Add a hook for testing for recursion.
+ def parentof?(child)
+ if (self == child)
+ debug "parent is equal to child"
+ return true
+ elsif defined? @parent and @parent.parentof?(child)
+ debug "My parent is parent of child"
+ return true
+ else
+ return false
+ end
+ end
+
+ # Remove an object. The argument determines whether the object's
+ # subscriptions get eliminated, too.
+ def remove(rmdeps = true)
+ # This is hackish (mmm, cut and paste), but it works for now, and it's
+ # better than warnings.
+ @parameters.each do |name, obj|
+ obj.remove
+ end
+ @parameters.clear
+ self.class.delete(self)
+
+ @parent = nil
+
+ # Remove the reference to the provider.
+ if self.provider
+ @provider.clear
+ @provider = nil
+ end
+ end
+
+ ###############################
+ # Code related to evaluating the resources.
+
+ # This method is responsible for collecting property changes we always
+ # descend into the children before we evaluate our current properties.
+ # This returns any changes resulting from testing, thus 'collect' rather
+ # than 'each'.
+ def evaluate
+ if self.provider.is_a?(Puppet::Provider)
+ unless provider.class.suitable?
+ raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
+ end
+ end
+ #Puppet.err "Evaluating %s" % self.path.join(":")
+ unless defined? @evalcount
+ self.err "No evalcount defined on '%s' of type '%s'" %
+ [self.title,self.class]
+ @evalcount = 0
+ end
+ @evalcount += 1
+
+ if p = self.provider and p.respond_to?(:prefetch)
+ p.prefetch
+ end
+
+ # this only operates on properties, not properties + children
+ # it's important that we call retrieve() on the type instance,
+ # not directly on the property, because it allows the type to override
+ # the method, like pfile does
+ currentvalues = self.retrieve
+
+ changes = propertychanges(currentvalues).flatten
+
+ # now record how many changes we've resulted in
+ if changes.length > 0
+ self.debug "%s change(s)" %
+ [changes.length]
+ end
+
+ # If we're in noop mode, we don't want to store the checked time,
+ # because it will result in the resource not getting scheduled if
+ # someone were to apply the catalog in non-noop mode.
+ # We're going to go ahead and record that we checked if there were
+ # no changes, since it's unlikely it will affect the scheduling.
+ noop = noop?
+ if ! noop or (noop && changes.length == 0)
+ self.cache(:checked, Time.now)
+ end
+ return changes.flatten
+ end
+
+ # Flush the provider, if it supports it. This is called by the
+ # transaction.
+ def flush
+ if self.provider and self.provider.respond_to?(:flush)
+ self.provider.flush
+ end
+ end
+
+ # if all contained objects are in sync, then we're in sync
+ # FIXME I don't think this is used on the type instances any more,
+ # it's really only used for testing
+ def insync?(is)
+ insync = true
+
+ if property = @parameters[:ensure]
+ unless is.include? property
+ raise Puppet::DevError,
+ "The is value is not in the is array for '%s'" %
+ [property.name]
+ end
+ ensureis = is[property]
+ if property.insync?(ensureis) and property.should == :absent
+ return true
+ end
+ end
+
+ properties.each { |property|
+ unless is.include? property
+ raise Puppet::DevError,
+ "The is value is not in the is array for '%s'" %
+ [property.name]
+ end
+
+ propis = is[property]
+ unless property.insync?(propis)
+ property.debug("Not in sync: %s vs %s" %
+ [propis.inspect, property.should.inspect])
+ insync = false
+ #else
+ # property.debug("In sync")
+ end
+ }
+
+ #self.debug("%s sync status is %s" % [self,insync])
+ return insync
+ end
+
+ # retrieve the current value of all contained properties
+ def retrieve
+ 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
+ }
+ end
+
+ # Are we running in noop mode?
+ def noop?
+ if defined?(@noop)
+ @noop
+ else
+ Puppet[:noop]
+ end
+ end
+
+ def noop
+ noop?
+ end
+
+ # Retrieve the changes associated with all of the properties.
+ def propertychanges(currentvalues)
+ # If we are changing the existence of the object, then none of
+ # the other properties matter.
+ changes = []
+ ensureparam = @parameters[:ensure]
+
+ # This allows resource types to have 'ensure' be a parameter, which allows them to
+ # just pass the parameter on to other generated resources.
+ ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
+ if ensureparam && !currentvalues.include?(ensureparam)
+ raise Puppet::DevError, "Parameter ensure defined but missing from current values"
+ end
+
+ if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
+ changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
+ # Else, if the 'ensure' property is correctly absent, then do
+ # nothing
+ elsif ensureparam and currentvalues[ensureparam] == :absent
+ return []
+ else
+ changes = properties().find_all { |property|
+ currentvalues[property] ||= :absent
+ ! property.insync?(currentvalues[property])
+ }.collect { |property|
+ Puppet::Transaction::Change.new(property, currentvalues[property])
+ }
+ end
+
+ if Puppet[:debug] and changes.length > 0
+ self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
+ end
+
+ changes
+ end
+
+ ###############################
+ # Code related to managing resource instances.
+ require 'puppet/transportable'
+
+ # Make 'new' private, so people have to use create instead.
+ class << self
+ private :new
+ end
+
+ # retrieve a named instance of the current type
+ def self.[](name)
+ raise "Global resource access is deprecated"
+ @objects[name] || @aliases[name]
+ end
+
+ # add an instance by name to the class list of instances
+ def self.[]=(name,object)
+ raise "Global resource storage is deprecated"
+ newobj = nil
+ if object.is_a?(Puppet::Type)
+ newobj = object
+ else
+ raise Puppet::DevError, "must pass a Puppet::Type object"
+ end
+
+ if exobj = @objects[name] and self.isomorphic?
+ msg = "Object '%s[%s]' already exists" %
+ [newobj.class.name, name]
+
+ if exobj.file and exobj.line
+ msg += ("in file %s at line %s" %
+ [object.file, object.line])
+ end
+ if object.file and object.line
+ msg += ("and cannot be redefined in file %s at line %s" %
+ [object.file, object.line])
+ end
+ error = Puppet::Error.new(msg)
+ raise error
+ else
+ #Puppet.info("adding %s of type %s to class list" %
+ # [name,object.class])
+ @objects[name] = newobj
+ end
+ end
+
+ # Create an alias. We keep these in a separate hash so that we don't encounter
+ # the objects multiple times when iterating over them.
+ def self.alias(name, obj)
+ raise "Global resource aliasing is deprecated"
+ if @objects.include?(name)
+ unless @objects[name] == obj
+ raise Puppet::Error.new(
+ "Cannot create alias %s: object already exists" %
+ [name]
+ )
+ end
+ end
+
+ if @aliases.include?(name)
+ unless @aliases[name] == obj
+ raise Puppet::Error.new(
+ "Object %s already has alias %s" %
+ [@aliases[name].name, name]
+ )
+ end
+ end
+
+ @aliases[name] = obj
+ end
+
+ # remove all of the instances of a single type
+ def self.clear
+ raise "Global resource removal is deprecated"
+ if defined? @objects
+ @objects.each do |name, obj|
+ obj.remove(true)
+ end
+ @objects.clear
+ end
+ if defined? @aliases
+ @aliases.clear
+ end
+ end
+
+ # Force users to call this, so that we can merge objects if
+ # necessary.
+ def self.create(args)
+ # Don't modify the original hash; instead, create a duplicate and modify it.
+ # We have to dup and use the ! so that it stays a TransObject if it is
+ # one.
+ hash = args.dup
+ symbolizehash!(hash)
+
+ # If we're the base class, then pass the info on appropriately
+ if self == Puppet::Type
+ type = nil
+ if hash.is_a? Puppet::TransObject
+ type = hash.type
+ else
+ # If we're using the type to determine object type, then delete it
+ if type = hash[:type]
+ hash.delete(:type)
+ end
+ end
+
+ # If they've specified a type and called on the base, then
+ # delegate to the subclass.
+ if type
+ if typeklass = self.type(type)
+ return typeklass.create(hash)
+ else
+ raise Puppet::Error, "Unknown type %s" % type
+ end
+ else
+ raise Puppet::Error, "No type found for %s" % hash.inspect
+ end
+ end
+
+ # Handle this new object being implicit
+ implicit = hash[:implicit] || false
+ if hash.include?(:implicit)
+ hash.delete(:implicit)
+ end
+
+ name = nil
+ unless hash.is_a? Puppet::TransObject
+ hash = self.hash2trans(hash)
+ end
+
+ # XXX This will have to change when transobjects change to using titles
+ title = hash.name
+
+ # create it anew
+ # if there's a failure, destroy the object if it got that far, but raise
+ # the error.
+ begin
+ obj = new(hash)
+ rescue => detail
+ Puppet.err "Could not create %s: %s" % [title, detail.to_s]
+ if obj
+ obj.remove(true)
+ end
+ raise
+ end
+
+ if implicit
+ obj.implicit = true
+ end
+
+ return obj
+ end
+
+ # remove a specified object
+ def self.delete(resource)
+ raise "Global resource removal is deprecated"
+ return unless defined? @objects
+ if @objects.include?(resource.title)
+ @objects.delete(resource.title)
+ end
+ if @aliases.include?(resource.title)
+ @aliases.delete(resource.title)
+ end
+ if @aliases.has_value?(resource)
+ names = []
+ @aliases.each do |name, otherres|
+ if otherres == resource
+ names << name
+ end
+ end
+ names.each { |name| @aliases.delete(name) }
+ end
+ end
+
+ # iterate across each of the type's instances
+ def self.each
+ raise "Global resource iteration is deprecated"
+ return unless defined? @objects
+ @objects.each { |name,instance|
+ yield instance
+ }
+ end
+
+ # does the type have an object with the given name?
+ def self.has_key?(name)
+ raise "Global resource access is deprecated"
+ return @objects.has_key?(name)
+ end
+
+ # Convert a hash to a TransObject.
+ def self.hash2trans(hash)
+ title = nil
+ if hash.include? :title
+ title = hash[:title]
+ hash.delete(:title)
+ elsif hash.include? self.namevar
+ title = hash[self.namevar]
+ hash.delete(self.namevar)
+
+ if hash.include? :name
+ raise ArgumentError, "Cannot provide both name and %s to %s" %
+ [self.namevar, self.name]
+ end
+ elsif hash[:name]
+ title = hash[:name]
+ hash.delete :name
+ end
+
+ if catalog = hash[:catalog]
+ hash.delete(:catalog)
+ end
+
+ raise(Puppet::Error, "You must specify a title for objects of type %s" % self.to_s) unless title
+
+ if hash.include? :type
+ unless self.validattr? :type
+ hash.delete :type
+ end
+ end
+
+ # okay, now make a transobject out of hash
+ begin
+ trans = Puppet::TransObject.new(title, self.name.to_s)
+ trans.catalog = catalog if catalog
+ hash.each { |param, value|
+ trans[param] = value
+ }
+ rescue => detail
+ raise Puppet::Error, "Could not create %s: %s" %
+ [name, detail]
+ end
+
+ return trans
+ end
+
+ # Retrieve all known instances. Either requires providers or must be overridden.
+ def self.instances
+ unless defined?(@providers) and ! @providers.empty?
+ raise Puppet::DevError, "%s has no providers and has not overridden 'instances'" % self.name
+ end
+
+ # Put the default provider first, then the rest of the suitable providers.
+ provider_instances = {}
+ providers_by_source.collect do |provider|
+ provider.instances.collect do |instance|
+ # We always want to use the "first" provider instance we find, unless the resource
+ # is already managed and has a different provider set
+ if other = provider_instances[instance.name]
+ Puppet.warning "%s %s found in both %s and %s; skipping the %s version" %
+ [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name]
+ next
+ end
+ provider_instances[instance.name] = instance
+
+ create(:name => instance.name, :provider => instance, :check => :all)
+ end
+ end.flatten.compact
+ end
+
+ # Return a list of one suitable provider per source, with the default provider first.
+ def self.providers_by_source
+ # Put the default provider first, then the rest of the suitable providers.
+ sources = []
+ [defaultprovider, suitableprovider].flatten.uniq.collect do |provider|
+ next if sources.include?(provider.source)
+
+ sources << provider.source
+ provider
+ end.compact
+ end
+
+ # Create the path for logging and such.
+ def pathbuilder
+ if p = parent
+ [p.pathbuilder, self.ref].flatten
+ else
+ [self.ref]
+ end
+ end
+
+ ###############################
+ # Add all of the meta parameters.
+ newmetaparam(:noop) do
+ desc "Boolean flag indicating whether work should actually
+ be done."
+
+ newvalues(:true, :false)
+ munge do |value|
+ case value
+ when true, :true, "true": @resource.noop = true
+ when false, :false, "false": @resource.noop = false
+ end
+ end
+ end
+
+ newmetaparam(:schedule) do
+ desc "On what schedule the object should be managed. You must create a
+ schedule object, and then reference the name of that object to use
+ that for your schedule::
+
+ schedule { daily:
+ period => daily,
+ range => \"2-4\"
+ }
+
+ exec { \"/usr/bin/apt-get update\":
+ schedule => daily
+ }
+
+ The creation of the schedule object does not need to appear in the
+ configuration before objects that use it."
+ end
+
+ newmetaparam(:check) do
+ desc "Propertys which should have their values retrieved
+ but which should not actually be modified. This is currently used
+ internally, but will eventually be used for querying, so that you
+ could specify that you wanted to check the install state of all
+ packages, and then query the Puppet client daemon to get reports
+ on all packages."
+
+ munge do |args|
+ # If they've specified all, collect all known properties
+ if args == :all
+ args = @resource.class.properties.find_all do |property|
+ # Only get properties supported by our provider
+ if @resource.provider
+ @resource.provider.class.supports_parameter?(property)
+ else
+ true
+ end
+ end.collect do |property|
+ property.name
+ end
+ end
+
+ unless args.is_a?(Array)
+ args = [args]
+ end
+
+ unless defined? @resource
+ self.devfail "No parent for %s, %s?" %
+ [self.class, self.name]
+ end
+
+ args.each { |property|
+ unless property.is_a?(Symbol)
+ property = property.intern
+ end
+ next if @resource.propertydefined?(property)
+
+ unless propertyklass = @resource.class.validproperty?(property)
+ if @resource.class.validattr?(property)
+ next
+ else
+ raise Puppet::Error, "%s is not a valid attribute for %s" %
+ [property, self.class.name]
+ end
+ end
+ next unless propertyklass.checkable?
+ @resource.newattr(property)
+ }
+ end
+ end
+
+ # We've got four relationship metaparameters, so this method is used
+ # to reduce code duplication between them.
+ def munge_relationship(param, values)
+ # We need to support values passed in as an array or as a
+ # resource reference.
+ result = []
+
+ # 'values' could be an array or a reference. If it's an array,
+ # it could be an array of references or an array of arrays.
+ if values.is_a?(Puppet::Type)
+ result << [values.class.name, values.title]
+ else
+ unless values.is_a?(Array)
+ devfail "Relationships must be resource references"
+ end
+ if values[0].is_a?(String) or values[0].is_a?(Symbol)
+ # we're a type/title array reference
+ values[0] = symbolize(values[0])
+ result << values
+ else
+ # we're an array of stuff
+ values.each do |value|
+ if value.is_a?(Puppet::Type)
+ result << [value.class.name, value.title]
+ elsif value.is_a?(Array)
+ value[0] = symbolize(value[0])
+ result << value
+ else
+ devfail "Invalid relationship %s" % value.inspect
+ end
+ end
+ end
+ end
+
+ if existing = self[param]
+ result = existing + result
+ end
+
+ result
+ end
+
+ newmetaparam(:loglevel) do
+ desc "Sets the level that information will be logged.
+ The log levels have the biggest impact when logs are sent to
+ syslog (which is currently the default)."
+ defaultto :notice
+
+ newvalues(*Puppet::Util::Log.levels)
+ newvalues(:verbose)
+
+ munge do |loglevel|
+ val = super(loglevel)
+ if val == :verbose
+ val = :info
+ end
+ val
+ end
+ end
+
+ newmetaparam(:alias) do
+ desc "Creates an alias for the object. Puppet uses this internally when you
+ provide a symbolic name::
+
+ file { sshdconfig:
+ path => $operatingsystem ? {
+ solaris => \"/usr/local/etc/ssh/sshd_config\",
+ default => \"/etc/ssh/sshd_config\"
+ },
+ source => \"...\"
+ }
+
+ service { sshd:
+ subscribe => file[sshdconfig]
+ }
+
+ When you use this feature, the parser sets ``sshdconfig`` as the name,
+ and the library sets that as an alias for the file so the dependency
+ lookup for ``sshd`` works. You can use this parameter yourself,
+ but note that only the library can use these aliases; for instance,
+ the following code will not work::
+
+ file { \"/etc/ssh/sshd_config\":
+ owner => root,
+ group => root,
+ alias => sshdconfig
+ }
+
+ file { sshdconfig:
+ mode => 644
+ }
+
+ There's no way here for the Puppet parser to know that these two stanzas
+ should be affecting the same file.
+
+ See the `LanguageTutorial language tutorial`:trac: for more information.
+
+ "
+
+ munge do |aliases|
+ unless aliases.is_a?(Array)
+ aliases = [aliases]
+ end
+
+ 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
+ self.fail("%s can not create alias %s: object already exists" % [@resource.title, other])
+ end
+ next
+ end
+
+ # LAK:FIXME Old-school, add the alias to the class.
+ @resource.class.alias(other, @resource)
+
+ # Newschool, add it to the catalog.
+ @resource.catalog.alias(@resource, other)
+ end
+ end
+ end
+
+ newmetaparam(:tag) do
+ desc "Add the specified tags to the associated resource. While all resources
+ are automatically tagged with as much information as possible
+ (e.g., each class and definition containing the resource), it can
+ be useful to add your own tags to a given resource.
+
+ Tags are currently useful for things like applying a subset of a
+ host's configuration::
+
+ puppetd --test --tags mytag
+
+ This way, when you're testing a configuration you can run just the
+ portion you're testing."
+
+ munge do |tags|
+ tags = [tags] unless tags.is_a? Array
+
+ tags.each do |tag|
+ @resource.tag(tag)
+ end
+ end
+ end
+
+ class RelationshipMetaparam < Puppet::Parameter
+ class << self
+ attr_accessor :direction, :events, :callback, :subclasses
+ end
+
+ @subclasses = []
+
+ def self.inherited(sub)
+ @subclasses << sub
+ end
+
+ def munge(rels)
+ @resource.munge_relationship(self.class.name, rels)
+ end
+
+ def validate_relationship
+ @value.each do |value|
+ unless @resource.catalog.resource(*value)
+ description = self.class.direction == :in ? "dependency" : "dependent"
+ fail Puppet::Error, "Could not find %s %s[%s] for %s" %
+ [description, value[0].to_s.capitalize, value[1], resource.ref]
+ end
+ end
+ end
+
+ # Create edges from each of our relationships. :in
+ # relationships are specified by the event-receivers, and :out
+ # relationships are specified by the event generator. This
+ # way 'source' and 'target' are consistent terms in both edges
+ # and events -- that is, an event targets edges whose source matches
+ # the event's source. The direction of the relationship determines
+ # which resource is applied first and which resource is considered
+ # to be the event generator.
+ def to_edges
+ @value.collect do |value|
+ # we just have a name and a type, and we need to convert it
+ # to an object...
+ tname, name = value
+ reference = Puppet::ResourceReference.new(tname, name)
+
+ # Either of the two retrieval attempts could have returned
+ # nil.
+ unless object = reference.resolve
+ self.fail "Could not retrieve dependency '%s' of %s" % [reference, @resource.ref]
+ end
+
+ # Are we requiring them, or vice versa? See the method docs
+ # for futher info on this.
+ if self.class.direction == :in
+ source = object
+ target = @resource
+ else
+ source = @resource
+ target = object
+ end
+
+ if method = self.class.callback
+ subargs = {
+ :event => self.class.events,
+ :callback => method
+ }
+ self.debug("subscribes to %s" % [object.ref])
+ else
+ # If there's no callback, there's no point in even adding
+ # a label.
+ subargs = nil
+ self.debug("requires %s" % [object.ref])
+ end
+
+ rel = Puppet::Relationship.new(source, target, subargs)
+ end
+ end
+ end
+
+ def self.relationship_params
+ RelationshipMetaparam.subclasses
+ end
+
+
+ # Note that the order in which the relationships params is defined
+ # matters. The labelled params (notify and subcribe) must be later,
+ # so that if both params are used, those ones win. It's a hackish
+ # solution, but it works.
+
+ newmetaparam(:require, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
+ desc "One or more objects that this object depends on.
+ This is used purely for guaranteeing that changes to required objects
+ happen before the dependent object. For instance::
+
+ # Create the destination directory before you copy things down
+ file { \"/usr/local/scripts\":
+ ensure => directory
+ }
+
+ file { \"/usr/local/scripts/myscript\":
+ source => \"puppet://server/module/myscript\",
+ mode => 755,
+ require => File[\"/usr/local/scripts\"]
+ }
+
+ Multiple dependencies can be specified by providing a comma-seperated list
+ of resources, enclosed in square brackets::
+
+ require => [ File[\"/usr/local\"], File[\"/usr/local/scripts\"] ]
+
+ Note that Puppet will autorequire everything that it can, and
+ there are hooks in place so that it's easy for resources to add new
+ ways to autorequire objects, so if you think Puppet could be
+ smarter here, let us know.
+
+ In fact, the above code was redundant -- Puppet will autorequire
+ any parent directories that are being managed; it will
+ automatically realize that the parent directory should be created
+ before the script is pulled down.
+
+ Currently, exec resources will autorequire their CWD (if it is
+ specified) plus any fully qualified paths that appear in the
+ command. For instance, if you had an ``exec`` command that ran
+ the ``myscript`` mentioned above, the above code that pulls the
+ file down would be automatically listed as a requirement to the
+ ``exec`` code, so that you would always be running againts the
+ most recent version.
+ "
+ end
+
+ newmetaparam(:subscribe, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :ALL_EVENTS, :callback => :refresh}) do
+ desc "One or more objects that this object depends on. Changes in the
+ subscribed to objects result in the dependent objects being
+ refreshed (e.g., a service will get restarted). For instance::
+
+ class nagios {
+ file { \"/etc/nagios/nagios.conf\":
+ source => \"puppet://server/module/nagios.conf\",
+ alias => nagconf # just to make things easier for me
+ }
+ service { nagios:
+ running => true,
+ subscribe => File[nagconf]
+ }
+ }
+
+ Currently the ``exec``, ``mount`` and ``service`` type support
+ refreshing.
+ "
+ end
+
+ newmetaparam(:before, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
+ desc %{This parameter is the opposite of **require** -- it guarantees
+ that the specified object is applied later than the specifying
+ object::
+
+ file { "/var/nagios/configuration":
+ source => "...",
+ recurse => true,
+ before => Exec["nagios-rebuid"]
+ }
+
+ exec { "nagios-rebuild":
+ command => "/usr/bin/make",
+ cwd => "/var/nagios/configuration"
+ }
+
+ This will make sure all of the files are up to date before the
+ make command is run.}
+ end
+
+ newmetaparam(:notify, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :ALL_EVENTS, :callback => :refresh}) do
+ desc %{This parameter is the opposite of **subscribe** -- it sends events
+ to the specified object::
+
+ file { "/etc/sshd_config":
+ source => "....",
+ notify => Service[sshd]
+ }
+
+ service { sshd:
+ ensure => running
+ }
+
+ This will restart the sshd service if the sshd config file changes.}
+ end
+
+ ###############################
+ # All of the provider plumbing for the resource types.
+ require 'puppet/provider'
+ require 'puppet/util/provider_features'
+
+ # Add the feature handling module.
+ extend Puppet::Util::ProviderFeatures
+
+ attr_reader :provider
+
+ # the Type class attribute accessors
+ class << self
+ attr_accessor :providerloader
+ attr_writer :defaultprovider
+ end
+
+ # Find the default provider.
+ def self.defaultprovider
+ unless defined? @defaultprovider and @defaultprovider
+ suitable = suitableprovider()
+
+ # Find which providers are a default for this system.
+ defaults = suitable.find_all { |provider| provider.default? }
+
+ # If we don't have any default we use suitable providers
+ defaults = suitable if defaults.empty?
+ max = defaults.collect { |provider| provider.defaultnum }.max
+ defaults = defaults.find_all { |provider| provider.defaultnum == max }
+
+ retval = nil
+ if defaults.length > 1
+ Puppet.warning(
+ "Found multiple default providers for %s: %s; using %s" %
+ [self.name, defaults.collect { |i| i.name.to_s }.join(", "),
+ defaults[0].name]
+ )
+ retval = defaults.shift
+ elsif defaults.length == 1
+ retval = defaults.shift
+ else
+ raise Puppet::DevError, "Could not find a default provider for %s" %
+ self.name
+ end
+
+ @defaultprovider = retval
+ end
+
+ return @defaultprovider
+ end
+
+ # Convert a hash, as provided by, um, a provider, into an instance of self.
+ def self.hash2obj(hash)
+ obj = nil
+
+ namevar = self.namevar
+ unless hash.include?(namevar) and hash[namevar]
+ raise Puppet::DevError, "Hash was not passed with namevar"
+ end
+
+ # if the obj already exists with that name...
+ if obj = self[hash[namevar]]
+ # We're assuming here that objects with the same name
+ # are the same object, which *should* be the case, assuming
+ # we've set up our naming stuff correctly everywhere.
+
+ # Mark found objects as present
+ hash.each { |param, value|
+ if property = obj.property(param)
+ elsif val = obj[param]
+ obj[param] = val
+ else
+ # There is a value on disk, but it should go away
+ obj[param] = :absent
+ end
+ }
+ else
+ # create a new obj, since no existing one seems to
+ # match
+ obj = self.create(namevar => hash[namevar])
+
+ # We can't just pass the hash in at object creation time,
+ # because it sets the should value, not the is value.
+ hash.delete(namevar)
+ hash.each { |param, value|
+ obj[param] = value unless obj.add_property_parameter(param)
+ }
+ end
+
+ return obj
+ end
+
+ # Retrieve a provider by name.
+ def self.provider(name)
+ name = Puppet::Util.symbolize(name)
+
+ # If we don't have it yet, try loading it.
+ unless @providers.has_key?(name)
+ @providerloader.load(name)
+ end
+ return @providers[name]
+ end
+
+ # Just list all of the providers.
+ def self.providers
+ @providers.keys
+ end
+
+ def self.validprovider?(name)
+ name = Puppet::Util.symbolize(name)
+
+ return (@providers.has_key?(name) && @providers[name].suitable?)
+ end
+
+ # Create a new provider of a type. This method must be called
+ # directly on the type that it's implementing.
+ def self.provide(name, options = {}, &block)
+ name = Puppet::Util.symbolize(name)
+
+ if obj = @providers[name]
+ Puppet.debug "Reloading %s %s provider" % [name, self.name]
+ unprovide(name)
+ end
+
+ parent = if pname = options[:parent]
+ options.delete(:parent)
+ if pname.is_a? Class
+ pname
+ else
+ if provider = self.provider(pname)
+ provider
+ else
+ raise Puppet::DevError,
+ "Could not find parent provider %s of %s" %
+ [pname, name]
+ end
+ end
+ else
+ Puppet::Provider
+ end
+
+ options[:resource_type] ||= self
+
+ self.providify
+
+ provider = genclass(name,
+ :parent => parent,
+ :hash => @providers,
+ :prefix => "Provider",
+ :block => block,
+ :include => feature_module,
+ :extend => feature_module,
+ :attributes => options
+ )
+
+ return provider
+ end
+
+ # Make sure we have a :provider parameter defined. Only gets called if there
+ # are providers.
+ def self.providify
+ return if @paramhash.has_key? :provider
+
+ newparam(:provider) do
+ desc "The specific backend for #{self.name.to_s} to use. You will
+ seldom need to specify this -- Puppet will usually discover the
+ appropriate provider for your platform."
+
+ # This is so we can refer back to the type to get a list of
+ # providers for documentation.
+ class << self
+ attr_accessor :parenttype
+ end
+
+ # We need to add documentation for each provider.
+ def self.doc
+ @doc + " Available providers are:\n\n" + parenttype().providers.sort { |a,b|
+ a.to_s <=> b.to_s
+ }.collect { |i|
+ "* **%s**: %s" % [i, parenttype().provider(i).doc]
+ }.join("\n")
+ end
+
+ defaultto {
+ @resource.class.defaultprovider.name
+ }
+
+ validate do |provider_class|
+ provider_class = provider_class[0] if provider_class.is_a? Array
+ if provider_class.is_a?(Puppet::Provider)
+ provider_class = provider_class.class.name
+ end
+
+ unless provider = @resource.class.provider(provider_class)
+ raise ArgumentError, "Invalid %s provider '%s'" % [@resource.class.name, provider_class]
+ end
+ end
+
+ munge do |provider|
+ provider = provider[0] if provider.is_a? Array
+ if provider.is_a? String
+ provider = provider.intern
+ end
+ @resource.provider = provider
+
+ if provider.is_a?(Puppet::Provider)
+ provider.class.name
+ else
+ provider
+ end
+ end
+ end.parenttype = self
+ end
+
+ def self.unprovide(name)
+ if @providers.has_key? name
+ rmclass(name,
+ :hash => @providers,
+ :prefix => "Provider"
+ )
+ if @defaultprovider and @defaultprovider.name == name
+ @defaultprovider = nil
+ end
+ end
+ end
+
+ # Return an array of all of the suitable providers.
+ def self.suitableprovider
+ if @providers.empty?
+ providerloader.loadall
+ end
+ @providers.find_all { |name, provider|
+ provider.suitable?
+ }.collect { |name, provider|
+ provider
+ }.reject { |p| p.name == :fake } # For testing
+ end
+
+ def provider=(name)
+ if name.is_a?(Puppet::Provider)
+ @provider = name
+ @provider.resource = self
+ elsif klass = self.class.provider(name)
+ @provider = klass.new(self)
+ else
+ raise ArgumentError, "Could not find %s provider of %s" %
+ [name, self.class.name]
+ end
+ end
+
+ ###############################
+ # All of the relationship code.
+
+ # Specify a block for generating a list of objects to autorequire. This
+ # makes it so that you don't have to manually specify things that you clearly
+ # require.
+ def self.autorequire(name, &block)
+ @autorequires ||= {}
+ @autorequires[name] = block
+ end
+
+ # Yield each of those autorequires in turn, yo.
+ def self.eachautorequire
+ @autorequires ||= {}
+ @autorequires.each { |type, block|
+ yield(type, block)
+ }
+ end
+
+ # Figure out of there are any objects we can automatically add as
+ # dependencies.
+ def autorequire
+ reqs = []
+ self.class.eachautorequire { |type, block|
+ # Ignore any types we can't find, although that would be a bit odd.
+ next unless typeobj = Puppet.type(type)
+
+ # Retrieve the list of names from the block.
+ next unless list = self.instance_eval(&block)
+ unless list.is_a?(Array)
+ list = [list]
+ end
+
+ # Collect the current prereqs
+ list.each { |dep|
+ obj = nil
+ # Support them passing objects directly, to save some effort.
+ unless dep.is_a? Puppet::Type
+ # Skip autorequires that we aren't managing
+ unless dep = rel_catalog.resource(type, dep)
+ next
+ end
+ end
+
+ reqs << Puppet::Relationship.new(dep, self)
+ }
+ }
+
+ return reqs
+ end
+
+ # Build the dependencies associated with an individual object.
+ def builddepends
+ # Handle the requires
+ self.class.relationship_params.collect do |klass|
+ if param = @parameters[klass.name]
+ param.to_edges
+ end
+ end.flatten.reject { |r| r.nil? }
+ end
+
+ # Does this resource have a relationship with the other? We have to
+ # check each object for both directions of relationship.
+ def requires?(other)
+ them = [other.class.name, other.title]
+ me = [self.class.name, self.title]
+ self.class.relationship_params.each do |param|
+ case param.direction
+ when :in: return true if v = self[param.name] and v.include?(them)
+ when :out: return true if v = other[param.name] and v.include?(me)
+ end
+ end
+ return false
+ end
+
+ # we've received an event
+ # we only support local events right now, so we can pass actual
+ # objects around, including the transaction object
+ # the assumption here is that container objects will pass received
+ # methods on to contained objects
+ # i.e., we don't trigger our children, our refresh() method calls
+ # refresh() on our children
+ def trigger(event, source)
+ trans = event.transaction
+ if @callbacks.include?(source)
+ [:ALL_EVENTS, event.event].each { |eventname|
+ if method = @callbacks[source][eventname]
+ if trans.triggered?(self, method) > 0
+ next
+ end
+ if self.respond_to?(method)
+ self.send(method)
+ end
+
+ trans.triggered(self, method)
+ end
+ }
+ end
+ end
+
+ # Unsubscribe from a given object, possibly with a specific event.
+ def unsubscribe(object, event = nil)
+ # First look through our own relationship params
+ [:require, :subscribe].each do |param|
+ if values = self[param]
+ newvals = values.reject { |d|
+ d == [object.class.name, object.title]
+ }
+ if newvals.length != values.length
+ self.delete(param)
+ self[param] = newvals
+ end
+ end
+ end
+ end
+
+ ###############################
+ # All of the scheduling code.
+
+ # Look up the schedule and set it appropriately. This is done after
+ # the instantiation phase, so that the schedule can be anywhere in the
+ # file.
+ def schedule
+ unless catalog
+ warning "Cannot schedule without a schedule-containing catalog"
+ return nil
+ end
+
+ unless defined? @schedule
+ if name = self[:schedule]
+ if sched = catalog.resource(:schedule, name)
+ @schedule = sched
+ else
+ self.fail "Could not find schedule %s" % name
+ end
+ else
+ @schedule = nil
+ end
+ end
+ @schedule
+ end
+
+ # Check whether we are scheduled to run right now or not.
+ def scheduled?
+ return true if Puppet[:ignoreschedules]
+ return true unless schedule = self.schedule
+
+ # We use 'checked' here instead of 'synced' because otherwise we'll
+ # end up checking most resources most times, because they will generally
+ # have been synced a long time ago (e.g., a file only gets updated
+ # once a month on the server and its schedule is daily; the last sync time
+ # will have been a month ago, so we'd end up checking every run).
+ return schedule.match?(self.cached(:checked).to_i)
+ end
+
+ ###############################
+ # All of the tagging code.
+ attr_reader :tags
+
+ # Add a new tag.
+ def tag(tag)
+ tag = tag.intern if tag.is_a? String
+ unless @tags.include? tag
+ @tags << tag
+ end
+ end
+
+ # Define the initial list of tags.
+ def tags=(list)
+ list = [list] unless list.is_a? Array
+
+ @tags = list.collect do |t|
+ case t
+ when String: t.intern
+ when Symbol: t
+ else
+ self.warning "Ignoring tag %s of type %s" % [tag.inspect, tag.class]
+ end
+ end
+
+ @tags << self.class.name unless @tags.include?(self.class.name)
+ end
+
+ # Figure out of any of the specified tags apply to this object. This is an
+ # OR operation.
+ def tagged?(tags)
+ tags = [tags] unless tags.is_a? Array
+
+ tags = tags.collect { |t| t.intern }
+
+ return tags.find { |tag| @tags.include? tag }
+ end
# Types (which map to resources in the languages) are entirely composed of
# attribute value pairs. Generally, Puppet calls any of these things an
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index ef010efda..c6ab2570c 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -839,6 +839,8 @@ module Puppet
# Keep track of all the files we found in the source, so we can purge
# appropriately.
sourced = []
+
+ success = false
@parameters[:source].should.each do |source|
sourceobj, path = uri2obj(source)
@@ -853,6 +855,8 @@ module Puppet
if desc == ""
next
end
+
+ success = true
# Now create a new child for every file returned in the list.
result += desc.split("\n").collect { |line|
@@ -888,6 +892,11 @@ module Puppet
return [result, sourced]
end
end
+
+ unless success
+ raise Puppet::Error, "None of the provided sources exist"
+ end
+
return [result, sourced]
end
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index f004f7c42..0cea39197 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -138,8 +138,8 @@ module Puppet
# that can't query versions.
return true
else
- self.debug "is is %s, latest %s is %s" %
- [is.inspect, @resource.name, @latest.inspect]
+ self.debug "%s %s is installed, latest is %s" %
+ [@resource.name, is.inspect, @latest.inspect]
end
when :absent
return true if is == :absent or is == :purged
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 0b668395d..100c9c377 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -158,6 +158,14 @@ module Puppet
newproperty(:password, :required_features => :manages_passwords) do
desc "The user's password, in whatever encrypted format the local machine requires. Be sure to enclose any value that includes a dollar sign ($) in single quotes (\')."
+
+ def change_to_s(currentvalue, newvalue)
+ if currentvalue == :absent
+ return "created password"
+ else
+ return "changed password"
+ end
+ end
end
newproperty(:groups) do
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 94c96db0c..d6de3e2e1 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -220,19 +220,14 @@ module Util
def binary(bin)
if bin =~ /^\//
- if FileTest.exists? bin
+ if FileTest.file? bin and FileTest.executable? bin
return bin
else
return nil
end
else
- # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
- x = ENV['PATH'].split(":").each do |dir|
- if FileTest.exists? File.join(dir, bin)
- return File.join(dir, bin)
- end
- end
- return nil
+ x = %x{which #{bin} 2>/dev/null}.chomp
+ return x
end
end
module_function :binary
@@ -321,6 +316,7 @@ module Util
$stdin.reopen("/dev/null")
$stdout.reopen(output_file)
$stderr.reopen(output_file)
+ 3.upto(256){|fd| IO::new(fd).close rescue nil}
if arguments[:gid]
Process.egid = arguments[:gid]
Process.gid = arguments[:gid] unless @@os == "Darwin"
diff --git a/lib/puppet/util/ldap/connection.rb b/lib/puppet/util/ldap/connection.rb
index f6530f853..70fe303c5 100644
--- a/lib/puppet/util/ldap/connection.rb
+++ b/lib/puppet/util/ldap/connection.rb
@@ -17,7 +17,17 @@ class Puppet::Util::Ldap::Connection
else
false
end
- new(Puppet[:ldapserver], Puppet[:ldapport], :ssl => ssl)
+
+ options = {}
+ options[:ssl] = ssl
+ if user = Puppet.settings[:ldapuser] and user != ""
+ options[:user] = user
+ if pass = Puppet.settings[:ldappassword] and pass != ""
+ options[:password] = pass
+ end
+ end
+
+ new(Puppet[:ldapserver], Puppet[:ldapport], options)
end
def close
diff --git a/lib/puppet/util/plist.rb b/lib/puppet/util/plist.rb
deleted file mode 100644
index d7a95da23..000000000
--- a/lib/puppet/util/plist.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#--
-##############################################################
-# Copyright 2006, Ben Bleything <ben@bleything.net> and #
-# Patrick May <patrick@hexane.org> #
-# #
-# Distributed under the MIT license. #
-##############################################################
-#++
-# = Plist
-#
-# This is the main file for plist. Everything interesting happens in Plist and Plist::Emit.
-
-require 'base64'
-require 'cgi'
-require 'stringio'
-
-require 'puppet/util/plist/generator'
-require 'puppet/util/plist/parser'
-
-module Plist
- VERSION = '3.0.0'
-end
-
diff --git a/lib/puppet/util/plist/generator.rb b/lib/puppet/util/plist/generator.rb
deleted file mode 100644
index c615ac43b..000000000
--- a/lib/puppet/util/plist/generator.rb
+++ /dev/null
@@ -1,225 +0,0 @@
-#--###########################################################
-# Copyright 2006, Ben Bleything <ben@bleything.net> and #
-# Patrick May <patrick@hexane.org> #
-# #
-# Distributed under the MIT license. #
-##############################################################
-#++
-# See Plist::Emit.
-module Plist
- # === Create a plist
- # You can dump an object to a plist in one of two ways:
- #
- # * <tt>Plist::Emit.dump(obj)</tt>
- # * <tt>obj.to_plist</tt>
- # * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
- #
- # The following Ruby classes are converted into native plist types:
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
- # * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
- # * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
- # * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
- #
- # For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
- module Emit
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
- def to_plist(envelope = true)
- return Plist::Emit.dump(self, envelope)
- end
-
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
- def save_plist(filename)
- Plist::Emit.save_plist(self, filename)
- end
-
- # The following Ruby classes are converted into native plist types:
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
- #
- # Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
- #
- # +IO+ and +StringIO+ objects are encoded and placed in <data> elements; other objects are <tt>Marshal.dump</tt>'ed unless they implement +to_plist_node+.
- #
- # The +envelope+ parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer. Set it to false if you only want the fragment.
- def self.dump(obj, envelope = true)
- output = plist_node(obj)
-
- output = wrap(output) if envelope
-
- return output
- end
-
- # Writes the serialized object's plist to the specified filename.
- def self.save_plist(obj, filename)
- File.open(filename, 'wb') do |f|
- f.write(obj.to_plist)
- end
- end
-
- private
- def self.plist_node(element)
- output = ''
-
- if element.respond_to? :to_plist_node
- output << element.to_plist_node
- else
- case element
- when Array
- if element.empty?
- output << "<array/>\n"
- else
- output << tag('array') {
- element.collect {|e| plist_node(e)}
- }
- end
- when Hash
- if element.empty?
- output << "<dict/>\n"
- else
- inner_tags = []
-
- element.keys.sort.each do |k|
- v = element[k]
- inner_tags << tag('key', CGI::escapeHTML(k.to_s))
- inner_tags << plist_node(v)
- end
-
- output << tag('dict') {
- inner_tags
- }
- end
- when true, false
- output << "<#{element}/>\n"
- when Time
- output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
- when Date # also catches DateTime
- output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
- when String, Symbol, Fixnum, Bignum, Integer, Float
- output << tag(element_type(element), CGI::escapeHTML(element.to_s))
- when IO, StringIO
- element.rewind
- contents = element.read
- # note that apple plists are wrapped at a different length then
- # what ruby's base64 wraps by default.
- # I used #encode64 instead of #b64encode (which allows a length arg)
- # because b64encode is b0rked and ignores the length arg.
- data = "\n"
- Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
- output << tag('data', data)
- else
- output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
- data = "\n"
- Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
- output << tag('data', data )
- end
- end
-
- return output
- end
-
- def self.comment(content)
- return "<!-- #{content} -->\n"
- end
-
- def self.tag(type, contents = '', &block)
- out = nil
-
- if block_given?
- out = IndentedString.new
- out << "<#{type}>"
- out.raise_indent
-
- out << block.call
-
- out.lower_indent
- out << "</#{type}>"
- else
- out = "<#{type}>#{contents.to_s}</#{type}>\n"
- end
-
- return out.to_s
- end
-
- def self.wrap(contents)
- output = ''
-
- output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
- output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
- output << '<plist version="1.0">' + "\n"
-
- output << contents
-
- output << '</plist>' + "\n"
-
- return output
- end
-
- def self.element_type(item)
- return case item
- when String, Symbol: 'string'
- when Fixnum, Bignum, Integer: 'integer'
- when Float: 'real'
- else
- raise "Don't know about this data type... something must be wrong!"
- end
- end
- private
- class IndentedString #:nodoc:
- attr_accessor :indent_string
-
- @@indent_level = 0
-
- def initialize(str = "\t")
- @indent_string = str
- @contents = ''
- end
-
- def to_s
- return @contents
- end
-
- def raise_indent
- @@indent_level += 1
- end
-
- def lower_indent
- @@indent_level -= 1 if @@indent_level > 0
- end
-
- def <<(val)
- if val.is_a? Array
- val.each do |f|
- self << f
- end
- else
- # if it's already indented, don't bother indenting further
- unless val =~ /\A#{@indent_string}/
- indent = @indent_string * @@indent_level
-
- @contents << val.gsub(/^/, indent)
- else
- @contents << val
- end
-
- # it already has a newline, don't add another
- @contents << "\n" unless val =~ /\n$/
- end
- end
- end
- end
-end
-
-# we need to add this so sorting hash keys works properly
-class Symbol #:nodoc:
- def <=> (other)
- self.to_s <=> other.to_s
- end
-end
-
-class Array #:nodoc:
- include Plist::Emit
-end
-
-class Hash #:nodoc:
- include Plist::Emit
-end
-
diff --git a/lib/puppet/util/plist/parser.rb b/lib/puppet/util/plist/parser.rb
deleted file mode 100644
index 7308bfb9b..000000000
--- a/lib/puppet/util/plist/parser.rb
+++ /dev/null
@@ -1,226 +0,0 @@
-#--###########################################################
-# Copyright 2006, Ben Bleything <ben@bleything.net> and #
-# Patrick May <patrick@hexane.org> #
-# #
-# Distributed under the MIT license. #
-##############################################################
-#++
-# Plist parses Mac OS X xml property list files into ruby data structures.
-#
-# === Load a plist file
-# This is the main point of the library:
-#
-# r = Plist::parse_xml( filename_or_xml )
-module Plist
-# Note that I don't use these two elements much:
-#
-# + Date elements are returned as DateTime objects.
-# + Data elements are implemented as Tempfiles
-#
-# Plist::parse_xml will blow up if it encounters a data element.
-# If you encounter such an error, or if you have a Date element which
-# can't be parsed into a Time object, please send your plist file to
-# plist@hexane.org so that I can implement the proper support.
- def Plist::parse_xml( filename_or_xml )
- listener = Listener.new
- #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
- parser = StreamParser.new(filename_or_xml, listener)
- parser.parse
- listener.result
- end
-
- class Listener
- #include REXML::StreamListener
-
- attr_accessor :result, :open
-
- def initialize
- @result = nil
- @open = Array.new
- end
-
-
- def tag_start(name, attributes)
- @open.push PTag::mappings[name].new
- end
-
- def text( contents )
- @open.last.text = contents if @open.last
- end
-
- def tag_end(name)
- last = @open.pop
- if @open.empty?
- @result = last.to_ruby
- else
- @open.last.children.push last
- end
- end
- end
-
- class StreamParser
- def initialize( filename_or_xml, listener )
- @filename_or_xml = filename_or_xml
- @listener = listener
- end
-
- TEXT = /([^<]+)/
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
- DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
- COMMENT_START = /\A<!--/u
- COMMENT_END = /.*?-->/um
-
-
- def parse
- plist_tags = PTag::mappings.keys.join('|')
- start_tag = /<(#{plist_tags})([^>]*)>/i
- end_tag = /<\/(#{plist_tags})[^>]*>/i
-
- require 'strscan'
-
- contents = (
- if (File.exists? @filename_or_xml)
- File.open(@filename_or_xml) {|f| f.read}
- else
- @filename_or_xml
- end
- )
-
- @scanner = StringScanner.new( contents )
- until @scanner.eos?
- if @scanner.scan(COMMENT_START)
- @scanner.scan(COMMENT_END)
- elsif @scanner.scan(XMLDECL_PATTERN)
- elsif @scanner.scan(DOCTYPE_PATTERN)
- elsif @scanner.scan(start_tag)
- @listener.tag_start(@scanner[1], nil)
- if (@scanner[2] =~ /\/$/)
- @listener.tag_end(@scanner[1])
- end
- elsif @scanner.scan(TEXT)
- @listener.text(@scanner[1])
- elsif @scanner.scan(end_tag)
- @listener.tag_end(@scanner[1])
- else
- raise "Unimplemented element"
- end
- end
- end
- end
-
- class PTag
- @@mappings = { }
- def PTag::mappings
- @@mappings
- end
-
- def PTag::inherited( sub_class )
- key = sub_class.to_s.downcase
- key.gsub!(/^plist::/, '' )
- key.gsub!(/^p/, '') unless key == "plist"
-
- @@mappings[key] = sub_class
- end
-
- attr_accessor :text, :children
- def initialize
- @children = Array.new
- end
-
- def to_ruby
- raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
- end
- end
-
- class PList < PTag
- def to_ruby
- children.first.to_ruby if children.first
- end
- end
-
- class PDict < PTag
- def to_ruby
- dict = Hash.new
- key = nil
-
- children.each do |c|
- if key.nil?
- key = c.to_ruby
- else
- dict[key] = c.to_ruby
- key = nil
- end
- end
-
- dict
- end
- end
-
- class PKey < PTag
- def to_ruby
- CGI::unescapeHTML(text || '')
- end
- end
-
- class PString < PTag
- def to_ruby
- CGI::unescapeHTML(text || '')
- end
- end
-
- class PArray < PTag
- def to_ruby
- children.collect do |c|
- c.to_ruby
- end
- end
- end
-
- class PInteger < PTag
- def to_ruby
- text.to_i
- end
- end
-
- class PTrue < PTag
- def to_ruby
- true
- end
- end
-
- class PFalse < PTag
- def to_ruby
- false
- end
- end
-
- class PReal < PTag
- def to_ruby
- text.to_f
- end
- end
-
- require 'date'
- class PDate < PTag
- def to_ruby
- DateTime.parse(text)
- end
- end
-
- require 'base64'
- class PData < PTag
- def to_ruby
- data = Base64.decode64(text.gsub(/\s+/, ''))
-
- begin
- return Marshal.load(data)
- rescue Exception => e
- io = StringIO.new
- io.write data
- io.rewind
- return io
- end
- end
- end
-end
-
diff --git a/spec/unit/module.rb b/spec/unit/module.rb
index e79001ae1..4d66550b5 100755
--- a/spec/unit/module.rb
+++ b/spec/unit/module.rb
@@ -90,23 +90,44 @@ describe Puppet::Module, " when searching for templates" do
end
it "should use the main templatedir if no module is found" do
- Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates")
+ Puppet::Module.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Module.expects(:find).with("mymod", nil).returns(nil)
Puppet::Module.find_template("mymod/mytemplate").should == "/my/templates/mymod/mytemplate"
end
it "should return unqualified templates directly in the template dir" do
- Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates")
+ Puppet::Module.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Module.expects(:find).never
Puppet::Module.find_template("mytemplate").should == "/my/templates/mytemplate"
end
it "should use the environment templatedir if no module is found and an environment is specified" do
- Puppet.settings.expects(:value).with(:templatedir, "myenv").returns("/myenv/templates")
+ Puppet::Module.stubs(:templatepath).with("myenv").returns(["/myenv/templates"])
+ Puppet::Module.expects(:find).with("mymod", "myenv").returns(nil)
+ Puppet::Module.find_template("mymod/mytemplate", "myenv").should == "/myenv/templates/mymod/mytemplate"
+ end
+
+ it "should use first dir from environment templatedir if no module is found and an environment is specified" do
+ Puppet::Module.stubs(:templatepath).with("myenv").returns(["/myenv/templates", "/two/templates"])
Puppet::Module.expects(:find).with("mymod", "myenv").returns(nil)
Puppet::Module.find_template("mymod/mytemplate", "myenv").should == "/myenv/templates/mymod/mytemplate"
end
+ it "should use a valid dir when templatedir is a path for unqualified templates and the first dir contains template" do
+ Puppet::Module.stubs(:templatepath).returns(["/one/templates", "/two/templates"])
+ File.expects(:exists?).with("/one/templates/mytemplate").returns(true)
+ Puppet::Module.expects(:find).never
+ Puppet::Module.find_template("mytemplate").should == "/one/templates/mytemplate"
+ end
+
+ it "should use a valid dir when templatedir is a path for unqualified templates and only second dir contains template" do
+ Puppet::Module.stubs(:templatepath).returns(["/one/templates", "/two/templates"])
+ File.expects(:exists?).with("/one/templates/mytemplate").returns(false)
+ File.expects(:exists?).with("/two/templates/mytemplate").returns(true)
+ Puppet::Module.expects(:find).never
+ Puppet::Module.find_template("mytemplate").should == "/two/templates/mytemplate"
+ end
+
it "should use the node environment if specified" do
Puppet.settings.stubs(:value).returns.returns("/my/directory")
Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/my/modules")
diff --git a/spec/unit/network/client/master.rb b/spec/unit/network/client/master.rb
index 754fd0583..f55ba316c 100755
--- a/spec/unit/network/client/master.rb
+++ b/spec/unit/network/client/master.rb
@@ -397,4 +397,46 @@ describe Puppet::Network::Client::Master, " when using the cached catalog" do
@client.catalog.should equal(ral_config)
end
+
+ describe "when calling splay" do
+ it "should do nothing if splay is not enabled" do
+ Puppet.stubs(:[]).with(:splay).returns(false)
+ @client.expects(:rand).never
+ @client.send(:splay)
+ end
+
+ describe "when splay is enabled" do
+ before do
+ Puppet.stubs(:[]).with(:splay).returns(true)
+ Puppet.stubs(:[]).with(:splaylimit).returns(42)
+ end
+
+ it "should sleep for a random time" do
+ @client.expects(:rand).with(42).returns(42)
+ @client.expects(:sleep).with(42)
+ @client.send(:splay)
+ end
+
+ it "should inform that it is splayed" do
+ @client.stubs(:rand).with(42).returns(42)
+ @client.stubs(:sleep).with(42)
+ Puppet.expects(:info)
+ @client.send(:splay)
+ end
+
+ it "should set splay = true" do
+ @client.stubs(:rand).with(42).returns(42)
+ @client.stubs(:sleep).with(42)
+ @client.send(:splay)
+ @client.send(:splayed?).should == true
+ end
+
+ it "should do nothing if already splayed" do
+ @client.stubs(:rand).with(42).returns(42).at_most_once
+ @client.stubs(:sleep).with(42).at_most_once
+ @client.send(:splay)
+ @client.send(:splay)
+ end
+ end
+ end
end
diff --git a/spec/unit/parameter.rb b/spec/unit/parameter.rb
new file mode 100755
index 000000000..d6858c29d
--- /dev/null
+++ b/spec/unit/parameter.rb
@@ -0,0 +1,24 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/parameter'
+
+describe Puppet::Parameter do
+ describe "when returning the value" do
+ before do
+ @class = Class.new(Puppet::Parameter)
+ @class.initvars
+ @parameter = @class.new :resource => mock('resource')
+ end
+
+ it "should return nil if no value is set" do
+ @parameter.value.should be_nil
+ end
+
+ it "should return any set value" do
+ @parameter.value = "foo"
+ @parameter.value.should == "foo"
+ end
+ end
+end
diff --git a/spec/unit/parser/ast/vardef.rb b/spec/unit/parser/ast/vardef.rb
new file mode 100755
index 000000000..6bd355c89
--- /dev/null
+++ b/spec/unit/parser/ast/vardef.rb
@@ -0,0 +1,47 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::VarDef do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ describe "when evaluating" do
+
+ it "should evaluate arguments" do
+ name = mock 'name'
+ value = mock 'value'
+
+ name.expects(:safeevaluate).with(@scope)
+ value.expects(:safeevaluate).with(@scope)
+
+ vardef = Puppet::Parser::AST::VarDef.new :name => name, :value => value, :file => nil,
+ :line => nil
+ vardef.evaluate(@scope)
+ end
+
+ it "should be in append=false mode if called without append" do
+ name = stub 'name', :safeevaluate => "var"
+ value = stub 'value', :safeevaluate => "1"
+
+ @scope.expects(:setvar).with { |name,value,file,line,append| append == nil }
+
+ vardef = Puppet::Parser::AST::VarDef.new :name => name, :value => value, :file => nil,
+ :line => nil
+ vardef.evaluate(@scope)
+ end
+
+ it "should call scope in append mode if append is true" do
+ name = stub 'name', :safeevaluate => "var"
+ value = stub 'value', :safeevaluate => "1"
+
+ @scope.expects(:setvar).with { |name,value,file,line,append| append == true }
+
+ vardef = Puppet::Parser::AST::VarDef.new :name => name, :value => value, :file => nil,
+ :line => nil, :append => true
+ vardef.evaluate(@scope)
+ end
+
+ end
+end
diff --git a/spec/unit/parser/lexer.rb b/spec/unit/parser/lexer.rb
index fb666054d..fed1ade7d 100755
--- a/spec/unit/parser/lexer.rb
+++ b/spec/unit/parser/lexer.rb
@@ -135,7 +135,8 @@ describe Puppet::Parser::Lexer::TOKENS do
:QMARK => '?',
:BACKSLASH => '\\',
:FARROW => '=>',
- :PARROW => '+>'
+ :PARROW => '+>',
+ :APPENDS => '+='
}.each do |name, string|
it "should have a token named #{name.to_s}" do
Puppet::Parser::Lexer::TOKENS[name].should_not be_nil
diff --git a/spec/unit/parser/parser.rb b/spec/unit/parser/parser.rb
new file mode 100755
index 000000000..94b19be40
--- /dev/null
+++ b/spec/unit/parser/parser.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Parser do
+
+ AST = Puppet::Parser::AST
+
+ before :each do
+ @parser = Puppet::Parser::Parser.new :environment => "development"
+ end
+
+ describe "when parsing append operator" do
+
+ it "should not raise syntax errors" do
+ lambda { @parser.parse("$var += something") }.should_not raise_error
+ end
+
+ it "shouldraise syntax error on incomplete syntax " do
+ lambda { @parser.parse("$var += ") }.should raise_error
+ end
+
+ it "should call AST::VarDef with append=true" do
+ AST::VarDef.expects(:new).with { |h| h[:append] == true }
+ @parser.parse("$var += 2")
+ end
+
+ it "should work with arrays too" do
+ AST::VarDef.expects(:new).with { |h| h[:append] == true }
+ @parser.parse("$var += ['test']")
+ end
+
+ end
+end
diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb
new file mode 100755
index 000000000..ec8ab6d7d
--- /dev/null
+++ b/spec/unit/parser/scope.rb
@@ -0,0 +1,37 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Parser::Scope do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ @topscope = Puppet::Parser::Scope.new()
+ @scope.stubs(:parent).returns(@topscope)
+ end
+
+ describe Puppet::Parser::Scope, "when setvar is called with append=true" do
+
+ it "should raise error if the variable is already defined in this scope" do
+ @scope.setvar("var","1",nil,nil,false)
+ lambda { @scope.setvar("var","1",nil,nil,true) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "it should lookup current variable value" do
+ @scope.expects(:lookupvar).with("var").returns("2")
+ @scope.setvar("var","1",nil,nil,true)
+ end
+
+ it "it should store the concatenated string '42'" do
+ @topscope.setvar("var","4",nil,nil,false)
+ @scope.setvar("var","2",nil,nil,true)
+ @scope.lookupvar("var").should == "42"
+ end
+
+ it "it should store the concatenated array [4,2]" do
+ @topscope.setvar("var",[4],nil,nil,false)
+ @scope.setvar("var",[2],nil,nil,true)
+ @scope.lookupvar("var").should == [4,2]
+ end
+
+ end
+end
diff --git a/spec/unit/property.rb b/spec/unit/property.rb
new file mode 100755
index 000000000..e5b1e0013
--- /dev/null
+++ b/spec/unit/property.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/property'
+
+describe Puppet::Property do
+ describe "when setting the value" do
+ it "should just set the 'should' value" do
+ @class = Class.new(Puppet::Property)
+ @class.initvars
+ @property = @class.new :resource => mock('resource')
+
+ @property.expects(:should=).with("foo")
+ @property.value = "foo"
+ end
+ end
+
+ describe "when returning the value" do
+ before do
+ @class = Class.new(Puppet::Property)
+ @class.initvars
+ @property = @class.new :resource => mock('resource')
+ end
+
+ it "should return nil if no value is set" do
+ @property.value.should be_nil
+ end
+
+ it "should return any set 'should' value" do
+ @property.should = "foo"
+ @property.value.should == "foo"
+ end
+ end
+end
diff --git a/spec/unit/provider/service/daemontools.rb b/spec/unit/provider/service/daemontools.rb
new file mode 100644
index 000000000..29e9dd5be
--- /dev/null
+++ b/spec/unit/provider/service/daemontools.rb
@@ -0,0 +1,124 @@
+#!/usr/bin/env ruby
+#
+# Unit testing for the Daemontools service Provider
+#
+# author Brice Figureau
+#
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:service).provider(:daemontools)
+
+describe provider_class do
+
+ before(:each) do
+ # Create a mock resource
+ @resource = stub 'resource'
+
+ @provider = provider_class.new
+ @servicedir = "/etc/service"
+ @provider.servicedir=@servicedir
+ @daemondir = "/var/lib/service"
+ @provider.class.defpath=@daemondir
+
+ # A catch all; no parameters set
+ @resource.stubs(:[]).returns(nil)
+
+ # But set name, source and path (because we won't run
+ # the thing that will fetch the resource path from the provider)
+ @resource.stubs(:[]).with(:name).returns "myservice"
+ @resource.stubs(:[]).with(:ensure).returns :enabled
+ @resource.stubs(:[]).with(:path).returns @daemondir
+ @resource.stubs(:ref).returns "Service[myservice]"
+
+ @provider.stubs(:resource).returns @resource
+ end
+
+ it "should have a restartcmd method" do
+ @provider.should respond_to(:restartcmd)
+ end
+
+ it "should have a start method" do
+ @provider.should respond_to(:start)
+ end
+
+ it "should have a stop method" do
+ @provider.should respond_to(:stop)
+ end
+
+ it "should have an enabled? method" do
+ @provider.should respond_to(:enabled?)
+ end
+
+ it "should have an enable method" do
+ @provider.should respond_to(:enable)
+ end
+
+ it "should have a disable method" do
+ @provider.should respond_to(:disable)
+ end
+
+ describe "when starting" do
+ it "should call enable" do
+ @provider.expects(:enable)
+ @provider.start
+ end
+ end
+
+ describe "when stopping" do
+ it "should call disable" do
+ @provider.expects(:disable)
+ @provider.stop
+ end
+ end
+
+ describe "when enabling" do
+ it "should create a symlink between daemon dir and service dir" do
+ FileTest.stubs(:symlink?).returns(false)
+ File.expects(:symlink).with(File.join(@daemondir,"myservice"), File.join(@servicedir,"myservice")).returns(0)
+ @provider.enable
+ end
+ end
+
+ describe "when disabling" do
+ it "should stop and then remove the symlink between daemon dir and service dir" do
+ FileTest.stubs(:directory?).returns(false)
+ FileTest.stubs(:symlink?).returns(true)
+ File.expects(:unlink).with(File.join(@servicedir,"myservice")).returns(0)
+ @provider.stubs(:texecute).returns("")
+ @provider.disable
+ end
+ end
+
+ describe "when disabling" do
+ it "should also call 'svc -dx /etc/service/myservice'" do
+ FileTest.stubs(:directory?).returns(false)
+ FileTest.stubs(:symlink?).returns(true)
+ File.expects(:unlink).with(File.join(@servicedir,"myservice")).returns(0)
+ @provider.expects(:texecute).with("stop", [nil, '-dx', File.join(@servicedir,"myservice")]).returns ""
+ @provider.disable
+ end
+ end
+
+ describe "when checking status" do
+ it "should call the external command 'svstat /etc/service/myservice'" do
+ @provider.expects(:svstat).with(File.join(@servicedir,"myservice"))
+ @provider.status
+ end
+ end
+
+ describe "when checking status" do
+ it "and svstat fails, properly raise a Puppet::Error" do
+ @provider.expects(:svstat).with(File.join(@servicedir,"myservice")).raises(Puppet::ExecutionFailure, "failure")
+ lambda { @provider.status }.should raise_error(Puppet::Error, 'Could not get status for service Service[myservice]: failure')
+ end
+ it "and svstat returns up, then return :running" do
+ @provider.expects(:svstat).with(File.join(@servicedir,"myservice")).returns("/etc/service/myservice: up (pid 454) 954326 seconds")
+ @provider.status.should == :running
+ end
+ it "and svstat returns not running, then return :stopped" do
+ @provider.expects(:svstat).with(File.join(@servicedir,"myservice")).returns("/etc/service/myservice: supervise not running")
+ @provider.status.should == :stopped
+ end
+ end
+
+ end
diff --git a/spec/unit/provider/service/runit.rb b/spec/unit/provider/service/runit.rb
new file mode 100644
index 000000000..8eb53849b
--- /dev/null
+++ b/spec/unit/provider/service/runit.rb
@@ -0,0 +1,117 @@
+#!/usr/bin/env ruby
+#
+# Unit testing for the Runit service Provider
+#
+# author Brice Figureau
+#
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:service).provider(:runit)
+
+describe provider_class do
+
+ before(:each) do
+ # Create a mock resource
+ @resource = stub 'resource'
+
+ @provider = provider_class.new
+ @servicedir = "/etc/service"
+ @provider.servicedir=@servicedir
+ @daemondir = "/etc/sv"
+ @provider.class.defpath=@daemondir
+
+ # A catch all; no parameters set
+ @resource.stubs(:[]).returns(nil)
+
+ # But set name, source and path (because we won't run
+ # the thing that will fetch the resource path from the provider)
+ @resource.stubs(:[]).with(:name).returns "myservice"
+ @resource.stubs(:[]).with(:ensure).returns :enabled
+ @resource.stubs(:[]).with(:path).returns @daemondir
+ @resource.stubs(:ref).returns "Service[myservice]"
+
+ @provider.stubs(:resource).returns @resource
+ end
+
+ it "should have a restartcmd method" do
+ @provider.should respond_to(:restartcmd)
+ end
+
+ it "should have a start method" do
+ @provider.should respond_to(:start)
+ end
+
+ it "should have a stop method" do
+ @provider.should respond_to(:stop)
+ end
+
+ it "should have an enabled? method" do
+ @provider.should respond_to(:enabled?)
+ end
+
+ it "should have an enable method" do
+ @provider.should respond_to(:enable)
+ end
+
+ it "should have a disable method" do
+ @provider.should respond_to(:disable)
+ end
+
+ describe "when starting" do
+ it "should call enable" do
+ @provider.expects(:enable)
+ @provider.start
+ end
+ end
+
+ describe "when stopping" do
+ it "should execute external command 'sv stop /etc/service/myservice'" do
+ @provider.expects(:ucommand).with(:stop).returns("")
+ @provider.stop
+ end
+ end
+
+ describe "when enabling" do
+ it "should create a symlink between daemon dir and service dir" do
+ FileTest.stubs(:symlink?).returns(false)
+ File.expects(:symlink).with(File.join(@daemondir,"myservice"), File.join(@servicedir,"myservice")).returns(0)
+ @provider.enable
+ end
+ end
+
+ describe "when disabling" do
+ it "should remove the '/etc/service/myservice' symlink" do
+ FileTest.stubs(:directory?).returns(false)
+ FileTest.stubs(:symlink?).returns(true)
+ File.expects(:unlink).with(File.join(@servicedir,"myservice")).returns(0)
+ @provider.disable
+ end
+ end
+
+ describe "when checking status" do
+ it "should call the external command 'sv status /etc/sv/myservice'" do
+ @provider.expects(:sv).with('status',File.join(@daemondir,"myservice"))
+ @provider.status
+ end
+ end
+
+ describe "when checking status" do
+ it "and sv status fails, properly raise a Puppet::Error" do
+ @provider.expects(:sv).with('status',File.join(@daemondir,"myservice")).raises(Puppet::ExecutionFailure, "fail: /etc/sv/myservice: file not found")
+ lambda { @provider.status }.should raise_error(Puppet::Error, 'Could not get status for service Service[myservice]: fail: /etc/sv/myservice: file not found')
+ end
+ it "and sv status returns up, then return :running" do
+ @provider.expects(:sv).with('status',File.join(@daemondir,"myservice")).returns("run: /etc/sv/myservice: (pid 9029) 6s")
+ @provider.status.should == :running
+ end
+ it "and sv status returns not running, then return :stopped" do
+ @provider.expects(:sv).with('status',File.join(@daemondir,"myservice")).returns("fail: /etc/sv/myservice: runsv not running")
+ @provider.status.should == :stopped
+ end
+ it "and sv status returns a warning, then return :stopped" do
+ @provider.expects(:sv).with('status',File.join(@daemondir,"myservice")).returns("warning: /etc/sv/myservice: unable to open supervise/ok: file does not exist")
+ @provider.status.should == :stopped
+ end
+ end
+
+ end
diff --git a/spec/unit/provider/user/hpux.rb b/spec/unit/provider/user/hpux.rb
new file mode 100755
index 000000000..4129a7ab6
--- /dev/null
+++ b/spec/unit/provider/user/hpux.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:user).provider(:hpuxuseradd)
+
+describe provider_class do
+ # left from the useradd test... I have no clue what I'm doing.
+ before do
+ @resource = stub("resource", :name => "myuser", :managehome? => nil, :should => "fakeval", :[] => "fakeval")
+ @provider = provider_class.new(@resource)
+ end
+
+ it "should add -F when modifying a user" do
+ @resource.expects(:allowdupe?).returns true
+ @provider.expects(:execute).with { |args| args.include?("-F") }
+ @provider.uid = 1000
+ end
+
+ it "should add -F when deleting a user" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.expects(:execute).with { |args| args.include?("-F") }
+ @provider.delete
+ end
+end
diff --git a/spec/unit/type/file.rb b/spec/unit/type/file.rb
index 7f9688f0b..663c5dc15 100755
--- a/spec/unit/type/file.rb
+++ b/spec/unit/type/file.rb
@@ -69,6 +69,12 @@ describe Puppet::Type.type(:file) do
@filesource.server.stubs(:describe).raises(Puppet::Network::XMLRPCClientError.new("Testing"))
lambda { @file.retrieve }.should raise_error(Puppet::Error)
end
+
+ it "should fail during eval_generate if no remote sources exist" do
+ file = Puppet::Type.type(:file).create :path => "/foobar", :source => "/this/file/does/not/exist", :recurse => true
+
+ lambda { file.eval_generate }.should raise_error(Puppet::Error)
+ end
end
describe "when managing links" do
diff --git a/spec/unit/type/noop_metaparam.rb b/spec/unit/type/noop_metaparam.rb
index 540603ef9..98cb0409e 100755
--- a/spec/unit/type/noop_metaparam.rb
+++ b/spec/unit/type/noop_metaparam.rb
@@ -2,7 +2,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
-require 'puppet/metatype/metaparams'
+require 'puppet/type'
describe Puppet::Type.type(:file).attrclass(:noop) do
before do
diff --git a/spec/unit/util/ldap/connection.rb b/spec/unit/util/ldap/connection.rb
index 9392466c7..8bc85a620 100755
--- a/spec/unit/util/ldap/connection.rb
+++ b/spec/unit/util/ldap/connection.rb
@@ -152,5 +152,18 @@ describe Puppet::Util::Ldap::Connection do
Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:ssl] == false }
Puppet::Util::Ldap::Connection.instance
end
+
+ it "should set the ldapuser if one is set" do
+ Puppet.settings.expects(:value).with(:ldapuser).returns "foo"
+ Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:user] == "foo" }
+ Puppet::Util::Ldap::Connection.instance
+ end
+
+ it "should set the ldapuser and ldappassword if both is set" do
+ Puppet.settings.expects(:value).with(:ldapuser).returns "foo"
+ Puppet.settings.expects(:value).with(:ldappassword).returns "bar"
+ Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:user] == "foo" and options[:password] == "bar" }
+ Puppet::Util::Ldap::Connection.instance
+ end
end
end
diff --git a/test/data/snippets/append.pp b/test/data/snippets/append.pp
new file mode 100644
index 000000000..28edeb177
--- /dev/null
+++ b/test/data/snippets/append.pp
@@ -0,0 +1,11 @@
+$var=['/tmp/file1','/tmp/file2']
+
+class arraytest {
+ $var += ['/tmp/file3', '/tmp/file4']
+ file {
+ $var:
+ content => "test"
+ }
+}
+
+include arraytest
diff --git a/test/language/functions.rb b/test/language/functions.rb
index 97429802b..50a61a148 100755
--- a/test/language/functions.rb
+++ b/test/language/functions.rb
@@ -379,6 +379,8 @@ class TestLangFunctions < Test::Unit::TestCase
scope = mkscope
parser = scope.compiler.parser
+ realize = Puppet::Parser::Functions.function(:realize)
+
# Make a definition
parser.newdefine("mytype")
@@ -434,6 +436,8 @@ class TestLangFunctions < Test::Unit::TestCase
def test_defined
scope = mkscope
parser = scope.compiler.parser
+
+ defined = Puppet::Parser::Functions.function(:defined)
parser.newclass("yayness")
parser.newdefine("rahness")
@@ -491,6 +495,8 @@ class TestLangFunctions < Test::Unit::TestCase
scope = mkscope
parser = scope.compiler.parser
+ include = Puppet::Parser::Functions.function(:include)
+
assert_raise(Puppet::ParseError, "did not throw error on missing class") do
scope.function_include("nosuchclass")
end
@@ -508,6 +514,8 @@ class TestLangFunctions < Test::Unit::TestCase
parser = mkparser
scope = mkscope(:parser => parser)
+ file = Puppet::Parser::Functions.function(:file)
+
file1 = tempfile
file2 = tempfile
file3 = tempfile
@@ -548,6 +556,8 @@ class TestLangFunctions < Test::Unit::TestCase
assert_equal("yay\n", %x{#{command}}, "command did not work")
assert_equal("yay-foo\n", %x{#{command} foo}, "command did not work")
+ generate = Puppet::Parser::Functions.function(:generate)
+
scope = mkscope
parser = scope.compiler.parser