summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-08-20 13:28:40 -0500
committerLuke Kanies <luke@madstop.com>2007-08-20 13:28:40 -0500
commit6467c21e15b8a28e627d1395f76fe8f42ee77d70 (patch)
treec36f4e350074a028ba6cc9f8e4230284e880ab46
parenta846ea900f9fa7a2baaa4fbd0742f080e7fd7a04 (diff)
The first pass where at least all of the snippet tests pass. I have unfortunately had to stop being so assiduous in my rewriting of tests, but I am in too much of a time crunch to do this "right". The basic structure is definitely in place, though, and from here it is a question of making the rest of the tests work and hopefully writing some sufficient new tests, rather than making the code itself work.
-rw-r--r--lib/puppet/network/handler/configuration.rb7
-rw-r--r--lib/puppet/network/handler/master.rb192
-rw-r--r--lib/puppet/parser/ast/astarray.rb63
-rw-r--r--lib/puppet/parser/ast/collection.rb2
-rw-r--r--lib/puppet/parser/ast/hostclass.rb1
-rw-r--r--lib/puppet/parser/collector.rb11
-rw-r--r--lib/puppet/parser/configuration.rb70
-rw-r--r--lib/puppet/parser/functions.rb7
-rw-r--r--lib/puppet/parser/interpreter.rb3
-rw-r--r--lib/puppet/parser/resource.rb319
-rw-r--r--lib/puppet/parser/resource/reference.rb2
-rw-r--r--lib/puppet/parser/scope.rb75
-rwxr-xr-xtest/language/ast/component.rb12
-rwxr-xr-xtest/language/configuration.rb16
-rwxr-xr-xtest/language/interpreter.rb156
-rwxr-xr-xtest/language/parser.rb17
-rwxr-xr-xtest/language/resource.rb425
-rwxr-xr-xtest/language/scope.rb250
-rw-r--r--test/lib/puppettest/parsertesting.rb21
-rw-r--r--test/lib/puppettest/resourcetesting.rb46
-rwxr-xr-xtest/network/handler/master.rb74
21 files changed, 718 insertions, 1051 deletions
diff --git a/lib/puppet/network/handler/configuration.rb b/lib/puppet/network/handler/configuration.rb
index c1c77a357..f1a20ee74 100644
--- a/lib/puppet/network/handler/configuration.rb
+++ b/lib/puppet/network/handler/configuration.rb
@@ -46,6 +46,8 @@ class Puppet::Network::Handler
# immediately. Mostly, this is so we can create the interpreter
# on-demand, which is easier for testing.
@options = options
+
+ set_server_facts
end
# Are we running locally, or are our clients networked?
@@ -58,7 +60,7 @@ class Puppet::Network::Handler
v = interpreter.configuration_version
# If we can find the node, then store the fact that the node
# has checked in.
- if node = node_handler.details(client)
+ if client and node = node_handler.details(client)
update_node_check(node)
end
@@ -95,6 +97,9 @@ class Puppet::Network::Handler
begin
config = interpreter.compile(node)
rescue Puppet::Error => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
Puppet.err detail
raise XMLRPC::FaultException.new(
1, detail.to_s
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index e889c1ba8..0aa50a426 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -21,66 +21,9 @@ class Puppet::Network::Handler
iface.add_method("int freshness()")
}
- # FIXME At some point, this should be autodocumenting.
- def addfacts(facts)
- # Add our server version to the fact list
- facts["serverversion"] = Puppet.version.to_s
-
- # And then add the server name and IP
- {"servername" => "fqdn",
- "serverip" => "ipaddress"
- }.each do |var, fact|
- if obj = Facter[fact]
- facts[var] = obj.value
- else
- Puppet.warning "Could not retrieve fact %s" % fact
- end
- end
-
- if facts["servername"].nil?
- host = Facter.value(:hostname)
- if domain = Facter.value(:domain)
- facts["servername"] = [host, domain].join(".")
- else
- facts["servername"] = host
- end
- end
- end
-
- # Manipulate the client name as appropriate.
- def clientname(name, ip, facts)
- # Always use the hostname from Facter.
- client = facts["hostname"]
- clientip = facts["ipaddress"]
- if Puppet[:node_name] == 'cert'
- if name
- client = name
- end
- if ip
- clientip = ip
- end
- end
-
- return client, clientip
- end
-
# Tell a client whether there's a fresh config for it
def freshness(client = nil, clientip = nil)
- if Puppet.features.rails? and Puppet[:storeconfigs]
- Puppet::Rails.connect
-
- host = Puppet::Rails::Host.find_or_create_by_name(client)
- host.last_freshcheck = Time.now
- if clientip and (! host.ip or host.ip == "" or host.ip == "NULL")
- host.ip = clientip
- end
- host.save
- end
- if defined? @interpreter
- return @interpreter.parsedate
- else
- return 0
- end
+ config_handler.version(client)
end
def initialize(hash = {})
@@ -121,104 +64,81 @@ class Puppet::Network::Handler
args[:Classes] = hash[:Classes]
end
- @interpreter = Puppet::Parser::Interpreter.new(args)
+ @config_handler = Puppet::Network::Handler.handler(:configuration).new(args)
end
+ # Call our various handlers; this handler is getting deprecated.
def getconfig(facts, format = "marshal", client = nil, clientip = nil)
- if @local
- # we don't need to do anything, since we should already
- # have raw objects
- Puppet.debug "Our client is local"
- else
- Puppet.debug "Our client is remote"
-
- # XXX this should definitely be done in the protocol, somehow
- case format
- when "marshal":
- Puppet.warning "You should upgrade your client. 'Marshal' will not be supported much longer."
- begin
- facts = Marshal::load(CGI.unescape(facts))
- rescue => detail
- raise XMLRPC::FaultException.new(
- 1, "Could not rebuild facts"
- )
- end
- when "yaml":
- begin
- facts = YAML.load(CGI.unescape(facts))
- rescue => detail
- raise XMLRPC::FaultException.new(
- 1, "Could not rebuild facts"
- )
- end
- else
- raise XMLRPC::FaultException.new(
- 1, "Unavailable config format %s" % format
- )
- end
- end
-
+ facts = decode_facts(facts)
client, clientip = clientname(client, clientip, facts)
- # Add any server-side facts to our server.
- addfacts(facts)
+ # Pass the facts to the fact handler
+ fact_handler.set(client, facts)
- retobjects = nil
+ # And get the configuration from the config handler
+ return config_handler.configuration(client)
+ end
- # This is hackish, but there's no "silence" option for benchmarks
- # right now
- if @local
- #begin
- retobjects = @interpreter.run(client, facts)
- #rescue Puppet::Error => detail
- # Puppet.err detail
- # raise XMLRPC::FaultException.new(
- # 1, detail.to_s
- # )
- #rescue => detail
- # Puppet.err detail.to_s
- # return ""
- #end
+ def local?
+ if defined? @local and @local
+ return true
else
- benchmark(:notice, "Compiled configuration for %s" % client) do
- begin
- retobjects = @interpreter.run(client, facts)
- rescue Puppet::Error => detail
- Puppet.err detail
- raise XMLRPC::FaultException.new(
- 1, detail.to_s
- )
- rescue => detail
- Puppet.err detail.to_s
- return ""
- end
+ return false
+ end
+ end
+
+ private
+
+ # Manipulate the client name as appropriate.
+ def clientname(name, ip, facts)
+ # Always use the hostname from Facter.
+ client = facts["hostname"]
+ clientip = facts["ipaddress"]
+ if Puppet[:node_name] == 'cert'
+ if name
+ client = name
end
+ if ip
+ clientip = ip
+ end
+ end
+
+ return client, clientip
+ end
+
+ def config_handler
+ unless defined? @config_handler
+ @config_handler = Puppet::Network::Handler.handler(:config).new :local => local?
end
+ @config_handler
+ end
+ #
+ def decode_facts(facts)
if @local
- return retobjects
+ # we don't need to do anything, since we should already
+ # have raw objects
+ Puppet.debug "Our client is local"
else
- str = nil
- case format
- when "marshal":
- str = Marshal::dump(retobjects)
- when "yaml":
- str = retobjects.to_yaml(:UseBlock => true)
- else
+ Puppet.debug "Our client is remote"
+
+ begin
+ facts = YAML.load(CGI.unescape(facts))
+ rescue => detail
raise XMLRPC::FaultException.new(
- 1, "Unavailable config format %s" % format
+ 1, "Could not rebuild facts"
)
end
- return CGI.escape(str)
end
+
+ return facts
end
- def local?
- if defined? @local and @local
- return true
- else
- return false
+ def fact_handler
+ unless defined? @fact_handler
+ @fact_handler = Puppet::Network::Handler.handler(:facts).new :local => local?
end
+ @fact_handler
end
end
end
diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb
index a0bd5bf89..c0212f919 100644
--- a/lib/puppet/parser/ast/astarray.rb
+++ b/lib/puppet/parser/ast/astarray.rb
@@ -21,45 +21,38 @@ class Puppet::Parser::AST
# We basically always operate declaratively, and when we
# do we need to evaluate the settor-like statements first. This
# is basically variable and type-default declarations.
- if scope.declarative?
- # This is such a stupid hack. I've no real idea how to make a
- # "real" declarative language, so I hack it so it looks like
- # one, yay.
- settors = []
- others = []
+ # This is such a stupid hack. I've no real idea how to make a
+ # "real" declarative language, so I hack it so it looks like
+ # one, yay.
+ settors = []
+ others = []
- # Make a new array, so we don't have to deal with the details of
- # flattening and such
- items = []
-
- # First clean out any AST::ASTArrays
- @children.each { |child|
- if child.instance_of?(AST::ASTArray)
- child.each do |ac|
- if ac.class.settor?
- settors << ac
- else
- others << ac
- end
- end
- else
- if child.class.settor?
- settors << child
+ # Make a new array, so we don't have to deal with the details of
+ # flattening and such
+ items = []
+
+ # First clean out any AST::ASTArrays
+ @children.each { |child|
+ if child.instance_of?(AST::ASTArray)
+ child.each do |ac|
+ if ac.class.settor?
+ settors << ac
else
- others << child
+ others << ac
end
end
- }
- rets = [settors, others].flatten.collect { |child|
- child.safeevaluate(:scope => scope)
- }
- return rets.reject { |o| o.nil? }
- else
- # If we're not declarative, just do everything in order.
- return @children.collect { |item|
- item.safeevaluate(:scope => scope)
- }.reject { |o| o.nil? }
- end
+ else
+ if child.class.settor?
+ settors << child
+ else
+ others << child
+ end
+ end
+ }
+ rets = [settors, others].flatten.collect { |child|
+ child.safeevaluate(:scope => scope)
+ }
+ return rets.reject { |o| o.nil? }
end
def push(*ary)
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb
index c817b5c5e..7daf031cf 100644
--- a/lib/puppet/parser/ast/collection.rb
+++ b/lib/puppet/parser/ast/collection.rb
@@ -20,7 +20,7 @@ class Collection < AST::Branch
newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form)
- scope.newcollection(newcoll)
+ scope.configuration.add_collection(newcoll)
newcoll
end
diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb
index d1ce370da..9b60c692f 100644
--- a/lib/puppet/parser/ast/hostclass.rb
+++ b/lib/puppet/parser/ast/hostclass.rb
@@ -27,7 +27,6 @@ class Puppet::Parser::AST
# Verify that we haven't already been evaluated, and if we have been evaluated,
# make sure that we match the class.
if existing_scope = scope.class_scope(self)
- raise "Fix this portion of the code -- check that the scopes match classes"
#if existing_scope.source.object_id == self.object_id
Puppet.debug "%s class already evaluated" % @type
return nil
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index 6c49c6d57..0846c40ab 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -81,7 +81,7 @@ class Puppet::Parser::Collector
# If there are no more resources to find, delete this from the list
# of collections.
if @resources.empty?
- @scope.collections.delete(self)
+ @scope.configuration.delete_collection(self)
end
return result
@@ -94,7 +94,7 @@ class Puppet::Parser::Collector
else
method = :virtual?
end
- scope.resources.find_all do |resource|
+ scope.configuration.resources.find_all do |resource|
resource.type == @type and resource.send(method) and match?(resource)
end
end
@@ -117,13 +117,6 @@ class Puppet::Parser::Collector
return objects
end
end
-
-# if objects and ! objects.empty?
-# objects.each { |r| r.virtual = false }
-# return objects
-# else
-# return false
-# end
end
def initialize(scope, type, equery, vquery, form)
diff --git a/lib/puppet/parser/configuration.rb b/lib/puppet/parser/configuration.rb
index 617d7d231..90812899a 100644
--- a/lib/puppet/parser/configuration.rb
+++ b/lib/puppet/parser/configuration.rb
@@ -60,7 +60,7 @@ class Puppet::Parser::Configuration
evaluate_main()
- evaluate_ast_nodes()
+ evaluate_ast_node()
evaluate_classes()
@@ -73,9 +73,32 @@ class Puppet::Parser::Configuration
return extract()
end
- # Should the scopes behave declaratively?
- def declarative?
- true
+ # FIXME There are no tests for this.
+ def delete_collection(coll)
+ @collections.delete(coll) if @collections.include?(coll)
+ end
+
+ # FIXME There are no tests for this.
+ def delete_resource(resource)
+ @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref)
+
+ @resource_graph.remove_vertex!(resource) if @resource_graph.vertex?(resource)
+ end
+
+ # Evaluate each class in turn. If there are any classes we can't find,
+ # just tag the configuration and move on.
+ def evaluate_classes(classes = nil)
+ classes ||= node.classes
+ classes.each do |name|
+ if klass = @parser.findclass("", name)
+ # This will result in class_set getting called, which
+ # will in turn result in tags. Yay.
+ klass.safeevaluate(:scope => topscope)
+ else
+ Puppet.info "Could not find class %s for %s" % [name, node.name]
+ tag(name)
+ end
+ end
end
# Make sure we support the requested extraction format.
@@ -119,9 +142,11 @@ class Puppet::Parser::Configuration
# Create a new scope, with either a specified parent scope or
# using the top scope. Adds an edge between the scope and
# its parent to the graph.
- def newscope(parent = nil)
+ def newscope(parent, options = {})
parent ||= @topscope
- scope = Puppet::Parser::Scope.new(:configuration => self)
+ options[:configuration] = self
+ options[:parser] ||= self.parser
+ scope = Puppet::Parser::Scope.new(options)
@scope_graph.add_edge!(parent, scope)
scope
end
@@ -141,6 +166,11 @@ class Puppet::Parser::Configuration
@resource_overrides[resource.ref]
end
+ # Return a list of all resources.
+ def resources
+ @resource_table.values
+ end
+
# Store a resource override.
def store_override(override)
override.override = true
@@ -179,7 +209,7 @@ class Puppet::Parser::Configuration
astnode = nil
#nodes = @parser.nodes
@node.names.each do |name|
- break if astnode = @parser.nodes[name]
+ break if astnode = @parser.nodes[name.to_s.downcase]
end
unless astnode
@@ -192,21 +222,6 @@ class Puppet::Parser::Configuration
astnode.safeevaluate :scope => topscope
end
- # Evaluate each class in turn. If there are any classes we can't find,
- # just tag the configuration and move on.
- def evaluate_classes
- node.classes.each do |name|
- if klass = @parser.findclass("", name)
- # This will result in class_set getting called, which
- # will in turn result in tags. Yay.
- klass.safeevaluate(:scope => topscope)
- else
- Puppet.info "Could not find class %s for %s" % [name, node.name]
- tag(name)
- end
- end
- end
-
# Evaluate our collections and return true if anything returned an object.
# The 'true' is used to continue a loop, so it's important.
def evaluate_collections
@@ -305,8 +320,13 @@ class Puppet::Parser::Configuration
end
# Then add the resources.
- @resource_graph.adjacent(scope, :direction => :out).each do |vertex|
- bucket.push vertex.to_trans
+ if @resource_graph.vertex?(scope)
+ @resource_graph.adjacent(scope, :direction => :out).each do |vertex|
+ # Some resources don't get translated, e.g., virtual resources.
+ if obj = vertex.to_trans
+ bucket.push obj
+ end
+ end
end
end
@@ -396,7 +416,7 @@ class Puppet::Parser::Configuration
@tags = []
# Create our initial scope, our scope graph, and add the initial scope to the graph.
- @topscope = Puppet::Parser::Scope.new(:configuration => self, :type => "main", :name => "top")
+ @topscope = Puppet::Parser::Scope.new(:configuration => self, :type => "main", :name => "top", :parser => self.parser)
# For maintaining scope relationships.
@scope_graph = GRATR::Digraph.new
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 946501154..ad58c7040 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -109,7 +109,8 @@ module Functions
# Include the specified classes
newfunction(:include, :doc => "Evaluate one or more classes.") do |vals|
- klasses = evalclasses(*vals)
+ vals = [vals] unless vals.is_a?(Array)
+ klasses = configuration.evaluate_classes(vals)
missing = vals.find_all do |klass|
! klasses.include?(klass)
@@ -144,7 +145,7 @@ module Functions
tells you whether the current container is tagged with the specified tags.
The tags are ANDed, so that all of the specified tags must be included for
the function to return true.") do |vals|
- classlist = self.classlist
+ classlist = configuration.classlist
retval = true
vals.each do |val|
@@ -234,7 +235,7 @@ module Functions
vals = [vals] unless vals.is_a?(Array)
coll.resources = vals
- newcollection(coll)
+ configuration.add_collection(coll)
end
newfunction(:search, :doc => "Add another namespace for this class to search.
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index f0b9d0179..cf3027a5a 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -3,6 +3,7 @@ require 'timeout'
require 'puppet/rails'
require 'puppet/util/methodhelper'
require 'puppet/parser/parser'
+require 'puppet/parser/configuration'
require 'puppet/parser/scope'
# The interpreter is a very simple entry-point class that
@@ -93,7 +94,7 @@ class Puppet::Parser::Interpreter
def compile(node)
parsefiles()
- return Puppet::Parser::Configuration.new(node).compile
+ return Puppet::Parser::Configuration.new(node, @parser).compile
end
private
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 371f56ec1..eace88645 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -10,9 +10,9 @@ class Puppet::Parser::Resource
include Puppet::Util::Logging
attr_accessor :source, :line, :file, :scope, :rails_id
- attr_accessor :virtual, :override, :params, :translated
+ attr_accessor :virtual, :override, :translated
- attr_reader :exported
+ attr_reader :exported, :evaluated, :params
attr_writer :tags
@@ -24,7 +24,7 @@ class Puppet::Parser::Resource
end
# Set up some boolean test methods
- [:exported, :translated, :override].each do |method|
+ [:exported, :translated, :override, :virtual, :evaluated].each do |method|
newmeth = (method.to_s + "?").intern
define_method(newmeth) do
self.send(method)
@@ -43,47 +43,6 @@ class Puppet::Parser::Resource
end
end
- # Add default values from our definition.
- def adddefaults
- defaults = scope.lookupdefaults(self.type)
-
- defaults.each do |name, param|
- unless @params.include?(param.name)
- self.debug "Adding default for %s" % param.name
-
- @params[param.name] = param
- end
- end
- end
-
- # Add any metaparams defined in our scope. This actually adds any metaparams
- # from any parent scope, and there's currently no way to turn that off.
- def addmetaparams
- Puppet::Type.eachmetaparam do |name|
- next if self[name]
- if val = scope.lookupvar(name.to_s, false)
- unless val == :undefined
- set Param.new(:name => name, :value => val,
- :source => scope.source)
- end
- end
- end
- end
-
- # Add any overrides for this object.
- def addoverrides
- overrides = scope.configuration.resource_overrides(self)
- raise "fix this test"
-
- overrides.each do |over|
- self.merge(over)
- end
-
- # Remove the overrides, so that the configuration knows there
- # are none left.
- overrides.clear
- end
-
def builtin=(bool)
@ref.builtin = bool
end
@@ -92,7 +51,7 @@ class Puppet::Parser::Resource
def evaluate
if klass = @ref.definedtype
finish()
- scope.deleteresource(self)
+ scope.configuration.delete_resource(self)
return klass.evaluate(:scope => scope,
:type => self.type,
:title => self.title,
@@ -110,6 +69,8 @@ class Puppet::Parser::Resource
@evaluated = true
end
+ # Mark this resource as both exported and virtual,
+ # or remove the exported mark.
def exported=(value)
if value
@virtual = true
@@ -119,63 +80,71 @@ class Puppet::Parser::Resource
end
end
- def evaluated?
- if defined? @evaluated and @evaluated
- true
- else
- false
- end
- end
-
# Do any finishing work on this object, called before evaluation or
# before storage/translation.
def finish
- addoverrides()
- adddefaults()
- addmetaparams()
+ add_overrides()
+ add_defaults()
+ add_metaparams()
+ validate()
end
def initialize(options)
- options = symbolize_options(options)
-
- # Collect the options necessary to make the reference.
- refopts = [:type, :title].inject({}) do |hash, param|
- hash[param] = options[param]
- options.delete(param)
- hash
+ # Set all of the options we can.
+ options.each do |option, value|
+ if respond_to?(option.to_s + "=")
+ send(option.to_s + "=", value)
+ options.delete(option)
+ end
end
- @params = {}
- tmpparams = nil
- if tmpparams = options[:params]
- options.delete(:params)
+ [:scope, :source].each do |attribute|
+ unless self.send(attribute)
+ raise ArgumentError, "Resources require a %s" % attribute
+ end
end
- # Now set the rest of the options.
- set_options(options)
-
- @ref = Reference.new(refopts)
+ # Set up our reference.
+ if type = options[:type] and title = options[:title]
+ options.delete(:type)
+ options.delete(:title)
+ else
+ raise ArgumentError, "Resources require a type and title"
+ end
- requiredopts(:scope, :source)
+ @ref = Reference.new(:type => type, :title => title, :scope => self.scope)
- @ref.scope = self.scope
+ @params = {}
- if tmpparams
- tmpparams.each do |param|
- # We use the method here, because it does type-checking.
- set(param)
+ # Define all of the parameters
+ if params = options[:params]
+ options.delete(:params)
+ params.each do |param|
+ set_parameter(param)
end
end
+
+ # Throw an exception if we've got any arguments left to set.
+ unless options.empty?
+ raise ArgumentError, "Resources do not accept %s" % options.keys.collect { |k| k.to_s }.join(", ")
+ end
end
- # Merge an override resource in.
+ # Merge an override resource in. This will throw exceptions if
+ # any overrides aren't allowed.
def merge(resource)
+ # Test the resource scope, to make sure the resource is even allowed
+ # to override.
+ unless self.source.object_id == resource.source.object_id || resource.source.child_of?(self.source)
+ raise Puppet::ParseError.new("Only subclasses can override parameters", resource.line, resource.file)
+ end
# Some of these might fail, but they'll fail in the way we want.
resource.params.each do |name, param|
- set(param)
+ override_parameter(param)
end
end
+ # Modify this resource in the Rails database. Poor design, yo.
def modify_rails(db_resource)
args = rails_args
args.each do |param, value|
@@ -226,23 +195,6 @@ class Puppet::Parser::Resource
@@paramcheck
end
- # Verify that all passed parameters are valid. This throws an error if
- # there's a problem, so we don't have to worry about the return value.
- def paramcheck(param)
- param = param.to_s
- # Now make sure it's a valid argument to our class. These checks
- # are organized in order of commonhood -- most types, it's a valid
- # argument and paramcheck is enabled.
- if @ref.typeclass.validattr?(param)
- true
- elsif %w{name title}.include?(param) # always allow these
- true
- elsif paramcheck?
- self.fail Puppet::ParseError, "Invalid parameter '%s' for type '%s'" %
- [param.inspect, @ref.type]
- end
- end
-
# A temporary occasion, until I get paths in the scopes figured out.
def path
to_s
@@ -253,59 +205,6 @@ class Puppet::Parser::Resource
@ref.to_s
end
- # You have to pass a Resource::Param to this.
- def set(param, value = nil, source = nil)
- if value and source
- param = Puppet::Parser::Resource::Param.new(
- :name => param, :value => value, :source => source
- )
- elsif ! param.is_a?(Puppet::Parser::Resource::Param)
- raise ArgumentError, "Must pass a parameter or all necessary values"
- end
- # Because definitions are now parse-time, I can paramcheck immediately.
- paramcheck(param.name)
-
- if current = @params[param.name]
- # This is where we'd ignore any equivalent values if we wanted to,
- # but that would introduce a lot of really bad ordering issues.
- if param.source.child_of?(current.source)
- if param.add
- # Merge with previous value.
- param.value = [ current.value, param.value ].flatten
- end
-
- # Replace it, keeping all of its info.
- @params[param.name] = param
- else
- if Puppet[:trace]
- puts caller
- end
- msg = "Parameter '%s' is already set on %s" %
- [param.name, self.to_s]
- if current.source.to_s != ""
- msg += " by %s" % current.source
- end
- if current.file or current.line
- fields = []
- fields << current.file if current.file
- fields << current.line.to_s if current.line
- msg += " at %s" % fields.join(":")
- end
- msg += "; cannot redefine"
- error = Puppet::ParseError.new(msg)
- error.file = param.file if param.file
- error.line = param.line if param.line
- raise error
- end
- else
- if self.source == param.source or param.source.child_of?(self.source)
- @params[param.name] = param
- else
- fail Puppet::ParseError, "Only subclasses can set parameters"
- end
- end
- end
-
def tags
unless defined? @tags
@tags = scope.tags
@@ -387,12 +286,102 @@ class Puppet::Parser::Resource
return obj
end
-
- def virtual?
- self.virtual
- end
private
+
+ # Add default values from our definition.
+ def add_defaults
+ scope.lookupdefaults(self.type).each do |name, param|
+ unless @params.include?(name)
+ self.debug "Adding default for %s" % name
+
+ @params[name] = param
+ end
+ end
+ end
+
+ # Add any metaparams defined in our scope. This actually adds any metaparams
+ # from any parent scope, and there's currently no way to turn that off.
+ def add_metaparams
+ Puppet::Type.eachmetaparam do |name|
+ # Skip metaparams that we already have defined.
+ next if @params[name]
+ if val = scope.lookupvar(name.to_s, false)
+ unless val == :undefined
+ set_parameter(name, val)
+ end
+ end
+ end
+ end
+
+ # Add any overrides for this object.
+ def add_overrides
+ if overrides = scope.configuration.resource_overrides(self)
+ overrides.each do |over|
+ self.merge(over)
+ end
+
+ # Remove the overrides, so that the configuration knows there
+ # are none left.
+ overrides.clear
+ end
+ end
+
+ # Accept a parameter from an override.
+ def override_parameter(param)
+ # This can happen if the override is defining a new parameter, rather
+ # than replacing an existing one.
+ unless current = @params[param.name]
+ @params[param.name] = param
+ return
+ end
+
+ # The parameter is already set. See if they're allowed to override it.
+ if param.source.child_of?(current.source)
+ if param.add
+ # Merge with previous value.
+ param.value = [ current.value, param.value ].flatten
+ end
+
+ # Replace it, keeping all of its info.
+ @params[param.name] = param
+ else
+ if Puppet[:trace]
+ puts caller
+ end
+ msg = "Parameter '%s' is already set on %s" %
+ [param.name, self.to_s]
+ if current.source.to_s != ""
+ msg += " by %s" % current.source
+ end
+ if current.file or current.line
+ fields = []
+ fields << current.file if current.file
+ fields << current.line.to_s if current.line
+ msg += " at %s" % fields.join(":")
+ end
+ msg += "; cannot redefine"
+ raise Puppet::ParseError.new(msg, param.line, param.file)
+ end
+ end
+
+ # Verify that all passed parameters are valid. This throws an error if
+ # there's a problem, so we don't have to worry about the return value.
+ def paramcheck(param)
+ param = param.to_s
+ # Now make sure it's a valid argument to our class. These checks
+ # are organized in order of commonhood -- most types, it's a valid
+ # argument and paramcheck is enabled.
+ if @ref.typeclass.validattr?(param)
+ true
+ elsif %w{name title}.include?(param) # always allow these
+ true
+ elsif paramcheck?
+ self.fail Puppet::ParseError, "Invalid parameter '%s' for type '%s'" %
+ [param, @ref.type]
+ end
+ end
+
def rails_args
return [:type, :title, :line, :exported].inject({}) do |hash, param|
# 'type' isn't a valid column name, so we have to use another name.
@@ -403,6 +392,26 @@ class Puppet::Parser::Resource
hash
end
end
-end
-# $Id$
+ # Define a parameter in our resource.
+ def set_parameter(param, value = nil)
+ if value
+ param = Puppet::Parser::Resource::Param.new(
+ :name => param, :value => value, :source => self.source
+ )
+ elsif ! param.is_a?(Puppet::Parser::Resource::Param)
+ raise ArgumentError, "Must pass a parameter or all necessary values"
+ end
+
+ # And store it in our parameter hash.
+ @params[param.name] = param
+ end
+
+ # Make sure the resource's parameters are all valid for the type.
+ def validate
+ @params.each do |name, param|
+ # Make sure it's a valid parameter.
+ paramcheck(name)
+ end
+ end
+end
diff --git a/lib/puppet/parser/resource/reference.rb b/lib/puppet/parser/resource/reference.rb
index 19d179660..b19dd2258 100644
--- a/lib/puppet/parser/resource/reference.rb
+++ b/lib/puppet/parser/resource/reference.rb
@@ -67,5 +67,3 @@ class Puppet::Parser::Resource::Reference
@typeclass
end
end
-
-# $Id$
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index cb6d98584..808362858 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -15,7 +15,7 @@ class Puppet::Parser::Scope
include Enumerable
include Puppet::Util::Errors
- attr_accessor :parent, :level, :interp, :source
+ attr_accessor :parent, :level, :parser, :source
attr_accessor :name, :type, :base, :keyword
attr_accessor :top, :translated, :exported, :virtual, :configuration
@@ -56,6 +56,11 @@ class Puppet::Parser::Scope
end
end
+ # Retrieve a given class scope from the configuration.
+ def class_scope(klass)
+ configuration.class_scope(klass)
+ end
+
# Are we the top scope?
def topscope?
@level == 1
@@ -67,7 +72,7 @@ class Puppet::Parser::Scope
def findclass(name)
@namespaces.each do |namespace|
- if r = interp.findclass(namespace, name)
+ if r = parser.findclass(namespace, name)
return r
end
end
@@ -76,7 +81,7 @@ class Puppet::Parser::Scope
def finddefine(name)
@namespaces.each do |namespace|
- if r = interp.finddefine(namespace, name)
+ if r = parser.finddefine(namespace, name)
return r
end
end
@@ -87,8 +92,7 @@ class Puppet::Parser::Scope
configuration.findresource(string, name)
end
- # Initialize our new scope. Defaults to having no parent and to
- # being declarative.
+ # Initialize our new scope. Defaults to having no parent.
def initialize(hash = {})
if hash.include?(:namespace)
if n = hash[:namespace]
@@ -115,7 +119,7 @@ class Puppet::Parser::Scope
# All of the defaults set for types. It's a hash of hashes,
# with the first key being the type, then the second key being
# the parameter.
- @defaultstable = Hash.new { |dhash,type|
+ @defaults = Hash.new { |dhash,type|
dhash[type] = {}
}
end
@@ -136,8 +140,8 @@ class Puppet::Parser::Scope
# then override them with any current values
# this should probably be done differently
- if @defaultstable.include?(type)
- @defaultstable[type].each { |var,value|
+ if @defaults.include?(type)
+ @defaults[type].each { |var,value|
values[var] = value
}
end
@@ -195,11 +199,9 @@ class Puppet::Parser::Scope
@namespaces.dup
end
- # Create a new scope.
- def newscope(hash = {})
- hash[:parent] = self
- #debug "Creating new scope, level %s" % [self.level + 1]
- return Puppet::Parser::Scope.new(hash)
+ # Create a new scope and set these options.
+ def newscope(options)
+ configuration.newscope(self, options)
end
# Is this class for a node? This is used to make sure that
@@ -256,7 +258,7 @@ class Puppet::Parser::Scope
# Add a new object to our object table and the global list, and do any necessary
# checks.
def setresource(resource)
- @configuration.store_resource(resource)
+ @configuration.store_resource(self, resource)
# Mark the resource as virtual or exported, as necessary.
if self.exported?
@@ -264,7 +266,6 @@ class Puppet::Parser::Scope
elsif self.virtual?
resource.virtual = true
end
- raise "setresource's tests aren't fixed"
return resource
end
@@ -274,19 +275,13 @@ class Puppet::Parser::Scope
# at the end.
def setoverride(resource)
@configuration.store_override(resource)
- raise "setoverride tests aren't fixed"
- if obj = @definedtable[resource.ref]
- obj.merge(resource)
- else
- @overridetable[resource.ref] << resource
- end
end
# Set defaults for a type. The typename should already be downcased,
# so that the syntax is isolated. We don't do any kind of type-checking
# here; instead we let the resource do it when the defaults are used.
def setdefaults(type, params)
- table = @defaultstable[type]
+ table = @defaults[type]
# if we got a single param, it'll be in its own array
params = [params] unless params.is_a?(Array)
@@ -294,17 +289,8 @@ class Puppet::Parser::Scope
params.each { |param|
#Puppet.debug "Default for %s is %s => %s" %
# [type,ary[0].inspect,ary[1].inspect]
- if @@declarative
- if table.include?(param.name)
- self.fail "Default already defined for %s { %s }" %
- [type,param.name]
- end
- else
- if table.include?(param.name)
- # we should maybe allow this warning to be turned off...
- Puppet.warning "Replacing default for %s { %s }" %
- [type,param.name]
- end
+ if table.include?(param.name)
+ raise Puppet::ParseError.new("Default already defined for %s { %s }; cannot redefine" % [type, param.name], param.line, param.file)
end
table[param.name] = param
}
@@ -312,23 +298,19 @@ 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 if we're declarative (which is the default).
+ # 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]
if @symtable.include?(name)
- if @@declarative
- error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
- if file
- error.file = file
- end
- if line
- error.line = line
- end
- raise error
- else
- Puppet.warning "Reassigning %s to %s" % [name,value]
+ error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
+ if file
+ error.file = file
+ end
+ if line
+ error.line = line
end
+ raise error
end
@symtable[name] = value
end
@@ -446,8 +428,7 @@ class Puppet::Parser::Scope
# Convert our resource to a TransBucket.
def to_trans
- raise "Scope#to_trans needs to be tested"
- bucket = Puppet::TransBucket.new ret
+ bucket = Puppet::TransBucket.new([])
case self.type
when "": bucket.type = "main"
diff --git a/test/language/ast/component.rb b/test/language/ast/component.rb
index 40543e9ab..13cf60857 100755
--- a/test/language/ast/component.rb
+++ b/test/language/ast/component.rb
@@ -17,10 +17,10 @@ class TestASTComponent < Test::Unit::TestCase
AST = Puppet::Parser::AST
def test_component
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
# Create a new definition
- klass = interp.newdefine "yayness",
+ klass = parser.newdefine "yayness",
:arguments => [["owner", stringobj("nobody")], %w{mode}],
:code => AST::ASTArray.new(
:children => [resourcedef("file", "/tmp/$name",
@@ -90,7 +90,7 @@ class TestASTComponent < Test::Unit::TestCase
# #539 - definitions should support both names and titles
def test_names_and_titles
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
[
{:name => "one", :title => "two"},
@@ -98,7 +98,7 @@ class TestASTComponent < Test::Unit::TestCase
].each_with_index do |hash, i|
# Create a definition that uses both name and title
- klass = interp.newdefine "yayness%s" % i
+ klass = parser.newdefine "yayness%s" % i
subscope = klass.subscope(scope, "yayness%s" % i)
@@ -133,8 +133,8 @@ class TestASTComponent < Test::Unit::TestCase
# Testing the root cause of #615. We should be using the fqname for the type, instead
# of just the short name.
def test_fully_qualified_types
- interp = mkinterp
- klass = interp.newclass("one::two")
+ parser = mkparser
+ klass = parser.newclass("one::two")
assert_equal("one::two", klass.classname, "Class did not get fully qualified class name")
end
diff --git a/test/language/configuration.rb b/test/language/configuration.rb
index aafdf8356..688782f7b 100755
--- a/test/language/configuration.rb
+++ b/test/language/configuration.rb
@@ -27,7 +27,12 @@ class TestConfiguration < Test::Unit::TestCase
end
def mkconfig(options = {})
- @config = Config.new(mknode, mkparser, options)
+ if node = options[:node]
+ options.delete(:node)
+ else
+ node = mknode
+ end
+ @config = Config.new(node, mkparser, options)
end
def test_initialize
@@ -111,7 +116,7 @@ class TestConfiguration < Test::Unit::TestCase
# Now that we've got the top scope, create a new, subscope
subscope = nil
assert_nothing_raised("Could not create subscope") do
- subscope = config.newscope
+ subscope = config.newscope(config.topscope)
end
assert_instance_of(Scope, subscope, "Did not create subscope")
assert(graph.edge?(config.topscope, subscope), "An edge between top scope and subscope was not added")
@@ -121,11 +126,12 @@ class TestConfiguration < Test::Unit::TestCase
assert_equal(config.topscope.object_id, config.parent(subscope).object_id, "Did not get correct parent scope from configuration")
assert_equal(config.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope")
- # Now create another, this time specifying the parent scope
+ # Now create another, this time specifying options
another = nil
assert_nothing_raised("Could not create subscope") do
- another = config.newscope(subscope)
+ another = config.newscope(subscope, :name => "testing")
end
+ assert_equal("testing", another.name, "did not set scope option correctly")
assert_instance_of(Scope, another, "Did not create second subscope")
assert(graph.edge?(subscope, another), "An edge between parent scope and second subscope was not added")
@@ -142,7 +148,7 @@ class TestConfiguration < Test::Unit::TestCase
# The heart of the action.
def test_compile
config = mkconfig
- [:set_node_parameters, :evaluate_main, :evaluate_ast_nodes, :evaluate_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method|
+ [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method|
config.expects(method)
end
config.expects(:extract).returns(:config)
diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb
index 070e2e77e..6b9aa7258 100755
--- a/test/language/interpreter.rb
+++ b/test/language/interpreter.rb
@@ -20,7 +20,6 @@ class TestInterpreter < PuppetTest::TestCase
include PuppetTest::ParserTesting
include PuppetTest::ResourceTesting
AST = Puppet::Parser::AST
- NodeDef = Puppet::Parser::Interpreter::NodeDef
# create a simple manifest that uses nodes to create a file
def mknodemanifest(node, file)
@@ -34,23 +33,13 @@ class TestInterpreter < PuppetTest::TestCase
return [file, createdfile]
end
- def test_simple
- file = tempfile()
- File.open(file, "w") { |f|
- f.puts "file { \"/etc\": owner => root }"
- }
- assert_nothing_raised {
- Puppet::Parser::Interpreter.new(:Manifest => file)
- }
- end
-
def test_reloadfiles
- hostname = Facter["hostname"].value
+ node = mknode(Facter["hostname"].value)
file = tempfile()
# Create a first version
- createdfile = mknodemanifest(hostname, file)
+ createdfile = mknodemanifest(node.name, file)
interp = nil
assert_nothing_raised {
@@ -59,61 +48,21 @@ class TestInterpreter < PuppetTest::TestCase
config = nil
assert_nothing_raised {
- config = interp.run(hostname, {})
+ config = interp.compile(node)
}
- sleep(1)
+ Puppet[:filetimeout] = -5
# Now create a new file
- createdfile = mknodemanifest(hostname, file)
+ createdfile = mknodemanifest(node.name, file)
newconfig = nil
assert_nothing_raised {
- newconfig = interp.run(hostname, {})
+ newconfig = interp.compile(node)
}
assert(config != newconfig, "Configs are somehow the same")
end
- # Make sure searchnode behaves as we expect.
- def test_nodesearch
- # We use two sources here to catch a weird bug where the default
- # node is used if the host isn't in the first source.
- interp = mkinterp
-
- # Make some nodes
- names = %w{node1 node2 node2.domain.com}
- interp.newnode names
- interp.newnode %w{default}
-
- nodes = {}
- # Make sure we can find them all, using the direct method
- names.each do |name|
- nodes[name] = interp.nodesearch_code(name)
- assert(nodes[name], "Could not find %s" % name)
- nodes[name].file = __FILE__
- end
-
- # Now let's try it with the nodesearch method
- names.each do |name|
- node = interp.nodesearch(name)
- assert(node, "Could not find #{name} via nodesearch")
- end
-
- # Make sure we find the default node when we search for nonexistent nodes
- assert_nothing_raised do
- default = interp.nodesearch("nosuchnode")
- assert(default, "Did not find default node")
- assert_equal("default", default.classname)
- end
-
- # Now make sure the longest match always wins
- node = interp.nodesearch(*%w{node2 node2.domain.com})
-
- assert(node, "Did not find node2")
- assert_equal("node2.domain.com", node.classname,
- "Did not get longest match")
- end
-
def test_parsedate
Puppet[:filetimeout] = 0
main = tempfile()
@@ -160,35 +109,6 @@ class TestInterpreter < PuppetTest::TestCase
newdate = interp.parsedate
assert(date != newdate, "Parsedate was not updated")
end
-
- # Make sure class, node, and define methods are case-insensitive
- def test_structure_case_insensitivity
- interp = mkinterp
-
- result = nil
- assert_nothing_raised do
- result = interp.newclass "Yayness"
- end
- assert_equal(result, interp.findclass("", "yayNess"))
-
- assert_nothing_raised do
- result = interp.newdefine "FunTest"
- end
- assert_equal(result, interp.finddefine("", "fUntEst"),
- "%s was not matched" % "fUntEst")
-
- assert_nothing_raised do
- result = interp.newnode("MyNode").shift
- end
- assert_equal(result, interp.nodesearch("mYnOde"),
- "mYnOde was not matched")
-
- assert_nothing_raised do
- result = interp.newnode("YayTest.Domain.Com").shift
- end
- assert_equal(result, interp.nodesearch("yaYtEst.domAin.cOm"),
- "yaYtEst.domAin.cOm was not matched")
- end
# Make sure our whole chain works.
def test_evaluate
@@ -444,70 +364,6 @@ class TestInterpreter < PuppetTest::TestCase
end
end
- def test_nodedef
- interp = mkinterp
- interp.newclass("base")
- interp.newclass("sub", :parent => "base")
- interp.newclass("other")
-
- node = nil
- assert_nothing_raised("Could not create a node definition") do
- node = NodeDef.new :name => "yay", :classes => "sub", :parameters => {"one" => "two", "three" => "four"}
- end
-
- scope = mkscope :interp => interp
- assert_nothing_raised("Could not evaluate the node definition") do
- node.evaluate(:scope => scope)
- end
-
- assert_equal("two", scope.lookupvar("one"), "NodeDef did not set variable")
- assert_equal("four", scope.lookupvar("three"), "NodeDef did not set variable")
-
- assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class")
- assert(scope.classlist.include?("base"), "NodeDef did not evaluate base class")
-
- # Now try a node def with multiple classes
- assert_nothing_raised("Could not create a node definition") do
- node = NodeDef.new :name => "yay", :classes => %w{sub other base}, :parameters => {"one" => "two", "three" => "four"}
- end
-
- scope = mkscope :interp => interp
- assert_nothing_raised("Could not evaluate the node definition") do
- node.evaluate(:scope => scope)
- end
-
- assert_equal("two", scope.lookupvar("one"), "NodeDef did not set variable")
- assert_equal("four", scope.lookupvar("three"), "NodeDef did not set variable")
-
- assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class")
- assert(scope.classlist.include?("other"), "NodeDef did not evaluate other class")
-
- # And a node def with no params
- assert_nothing_raised("Could not create a node definition with no params") do
- node = NodeDef.new :name => "yay", :classes => %w{sub other base}
- end
-
- scope = mkscope :interp => interp
- assert_nothing_raised("Could not evaluate the node definition") do
- node.evaluate(:scope => scope)
- end
-
- assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class")
- assert(scope.classlist.include?("other"), "NodeDef did not evaluate other class")
-
- # Now make sure nodedef doesn't fail when some classes are not defined (#687).
- assert_nothing_raised("Could not create a node definition with some invalid classes") do
- node = NodeDef.new :name => "yay", :classes => %w{base unknown}
- end
-
- scope = mkscope :interp => interp
- assert_nothing_raised("Could not evaluate the node definition with some invalid classes") do
- node.evaluate(:scope => scope)
- end
-
- assert(scope.classlist.include?("base"), "NodeDef did not evaluate class")
- end
-
# Make sure that reparsing is atomic -- failures don't cause a broken state, and we aren't subject
# to race conditions if someone contacts us while we're reparsing.
def test_atomic_reparsing
diff --git a/test/language/parser.rb b/test/language/parser.rb
index afffa9293..77595b155 100755
--- a/test/language/parser.rb
+++ b/test/language/parser.rb
@@ -1175,6 +1175,23 @@ file { "/tmp/yayness":
assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from alone file with no namespace")
assert_equal("alone::sub", klass.classname, "Incorrect class was returned")
end
+
+ # Make sure class, node, and define methods are case-insensitive
+ def test_structure_case_insensitivity
+ parser = mkparser
+
+ result = nil
+ assert_nothing_raised do
+ result = parser.newclass "Yayness"
+ end
+ assert_equal(result, parser.findclass("", "yayNess"))
+
+ assert_nothing_raised do
+ result = parser.newdefine "FunTest"
+ end
+ assert_equal(result, parser.finddefine("", "fUntEst"),
+ "%s was not matched" % "fUntEst")
+ end
end
# $Id$
diff --git a/test/language/resource.rb b/test/language/resource.rb
index 039c67216..73d516f51 100755
--- a/test/language/resource.rb
+++ b/test/language/resource.rb
@@ -11,149 +11,198 @@ class TestResource < PuppetTest::TestCase
include PuppetTest::ResourceTesting
Parser = Puppet::Parser
AST = Parser::AST
+ Resource = Puppet::Parser::Resource
Reference = Puppet::Parser::Resource::Reference
def setup
super
Puppet[:trace] = false
- @interp, @scope, @source = mkclassframing
end
def test_initialize
args = {:type => "resource", :title => "testing",
- :source => @source, :scope => @scope}
+ :source => "source", :scope => "scope"}
# Check our arg requirements
args.each do |name, value|
try = args.dup
try.delete(name)
- assert_raise(Puppet::DevError) do
+ assert_raise(ArgumentError, "Did not fail when %s was missing" % name) do
Parser::Resource.new(try)
end
end
- args[:params] = paramify @source, :one => "yay", :three => "rah"
+ Reference.expects(:new).with(:type => "resource", :title => "testing", :scope => "scope").returns(:ref)
res = nil
assert_nothing_raised do
res = Parser::Resource.new(args)
end
-
- # Make sure it got the parameters correctly.
- assert_equal("yay", res[:one])
- assert_equal("rah", res[:three])
-
- assert_equal({:one => "yay", :three => "rah"}, res.to_hash)
end
- def test_override
+ def test_merge
res = mkresource
+ other = mkresource
- # Now verify we can't override with any random class
- assert_raise(Puppet::ParseError) do
- res.set paramify(@scope.findclass("other"), "one" => "boo").shift
+ # First try the case where the resource is not allowed to override
+ res.source = "source1"
+ other.source = "source2"
+ other.source.expects(:child_of?).with("source1").returns(false)
+ assert_raise(Puppet::ParseError, "Allowed unrelated resources to override") do
+ res.merge(other)
end
- # And that we can with a subclass
- assert_nothing_raised do
- res.set paramify(@scope.findclass("sub1"), "one" => "boo").shift
- end
+ # Next try it when the sources are equal.
+ res.source = "source3"
+ other.source = res.source
+ other.source.expects(:child_of?).with("source3").never
+ params = {:a => :b, :c => :d}
+ other.expects(:params).returns(params)
+ res.expects(:override_parameter).with(:b)
+ res.expects(:override_parameter).with(:d)
+ res.merge(other)
+
+ # And then parentage is involved
+ other = mkresource
+ res.source = "source3"
+ other.source = "source4"
+ other.source.expects(:child_of?).with("source3").returns(true)
+ params = {:a => :b, :c => :d}
+ other.expects(:params).returns(params)
+ res.expects(:override_parameter).with(:b)
+ res.expects(:override_parameter).with(:d)
+ res.merge(other)
+ end
- # And that a different subclass can override a different parameter
- assert_nothing_raised do
- res.set paramify(@scope.findclass("sub2"), "three" => "boo").shift
- end
+ # the [] method
+ def test_array_accessors
+ res = mkresource
+ params = res.instance_variable_get("@params")
+ assert_nil(res[:missing], "Found a missing parameter somehow")
+ params[:something] = stub(:value => "yay")
+ assert_equal("yay", res[:something], "Did not correctly call value on the parameter")
- # But not the same one
- assert_raise(Puppet::ParseError) do
- res.set paramify(@scope.findclass("sub2"), "one" => "something").shift
- end
+ res.expects(:title).returns(:mytitle)
+ assert_equal(:mytitle, res[:title], "Did not call title when asked for it as a param")
end
- def check_paramadd(val1, val2, merged_val)
- res = mkresource :params => {"one" => val1}
- assert_nothing_raised do
- res.set Parser::Resource::Param.new(
- :name => "one", :value => val2,
- :add => true, :source => @scope.findclass("sub1"))
- end
- assert_equal(merged_val, res[:one])
+ # Make sure any defaults stored in the scope get added to our resource.
+ def test_add_defaults
+ res = mkresource
+ params = res.instance_variable_get("@params")
+ params[:a] = :b
+ res.scope.expects(:lookupdefaults).with(res.type).returns(:a => :replaced, :c => :d)
+ res.expects(:debug)
+
+ res.send(:add_defaults)
+ assert_equal(:d, params[:c], "Did not set default")
+ assert_equal(:b, params[:a], "Replaced parameter with default")
end
- def test_paramadd
- check_paramadd([], [], [])
- check_paramadd([], "rah", ["rah"])
- check_paramadd([], ["rah", "bah"], ["rah", "bah"])
-
- check_paramadd("yay", [], ["yay"])
- check_paramadd("yay", "rah", ["yay", "rah"])
- check_paramadd("yay", ["rah", "bah"], ["yay", "rah", "bah"])
-
- check_paramadd(["yay", "boo"], [], ["yay", "boo"])
- check_paramadd(["yay", "boo"], "rah", ["yay", "boo", "rah"])
- check_paramadd(["yay", "boo"], ["rah", "bah"],
- ["yay", "boo", "rah", "bah"])
+ def test_finish
+ res = mkresource
+ res.expects(:add_overrides)
+ res.expects(:add_defaults)
+ res.expects(:add_metaparams)
+ res.expects(:validate)
+ res.finish
end
- def test_merge
- # Start with the normal one
+ # Make sure we paramcheck our params
+ def test_validate
res = mkresource
+ params = res.instance_variable_get("@params")
+ params[:one] = :two
+ params[:three] = :four
+ res.expects(:paramcheck).with(:one)
+ res.expects(:paramcheck).with(:three)
+ res.send(:validate)
+ end
- # Now create a resource from a different scope
- other = mkresource :source => other, :params => {"one" => "boo"}
-
- # Make sure we can't merge it
- assert_raise(Puppet::ParseError) do
- res.merge(other)
- end
-
- # Make one from a subscope
- other = mkresource :source => "sub1", :params => {"one" => "boo"}
-
- # Make sure it merges
- assert_nothing_raised do
- res.merge(other)
- end
+ def test_override_parameter
+ res = mkresource
+ params = res.instance_variable_get("@params")
+
+ # There are three cases, with the second having two options:
+
+ # No existing parameter.
+ param = stub(:name => "myparam")
+ res.send(:override_parameter, param)
+ assert_equal(param, params["myparam"], "Override was not added to param list")
+
+ # An existing parameter that we can override.
+ source = stub(:child_of? => true)
+ # Start out without addition
+ params["param2"] = stub(:source => :whatever)
+ param = stub(:name => "param2", :source => source, :add => false)
+ res.send(:override_parameter, param)
+ assert_equal(param, params["param2"], "Override was not added to param list")
+
+ # Try with addition.
+ params["param2"] = stub(:value => :a, :source => :whatever)
+ param = stub(:name => "param2", :source => source, :add => true, :value => :b)
+ param.expects(:value=).with([:a, :b])
+ res.send(:override_parameter, param)
+ assert_equal(param, params["param2"], "Override was not added to param list")
+
+ # And finally, make sure we throw an exception when the sources aren't related
+ source = stub(:child_of? => false)
+ params["param2"] = stub(:source => :whatever, :file => :f, :line => :l)
+ old = params["param2"]
+ param = stub(:name => "param2", :source => source, :file => :f, :line => :l)
+ assert_raise(Puppet::ParseError, "Did not fail when params conflicted") do
+ res.send(:override_parameter, param)
+ end
+ assert_equal(old, params["param2"], "Param was replaced irrespective of conflict")
+ end
- assert_equal("boo", res["one"])
+ def test_set_parameter
+ res = mkresource
+ params = res.instance_variable_get("@params")
+
+ # First test the simple case: It's already a parameter
+ param = mock('param')
+ param.expects(:is_a?).with(Resource::Param).returns(true)
+ param.expects(:name).returns("pname")
+ res.send(:set_parameter, param)
+ assert_equal(param, params["pname"], "Parameter was not added to hash")
+
+ # Now the case where there's no value but it's not a param
+ param = mock('param')
+ param.expects(:is_a?).with(Resource::Param).returns(false)
+ assert_raise(ArgumentError, "Did not fail when a non-param was passed") do
+ res.send(:set_parameter, param)
+ end
+
+ # and the case where a value is passed in
+ param = stub :name => "pname", :value => "whatever"
+ Resource::Param.expects(:new).with(:name => "pname", :value => "myvalue", :source => res.source).returns(param)
+ res.send(:set_parameter, "pname", "myvalue")
+ assert_equal(param, params["pname"], "Did not put param in hash")
end
def test_paramcheck
- # First make a builtin resource
- res = nil
- assert_nothing_raised do
- res = Parser::Resource.new :type => "file", :title => tempfile(),
- :source => @source, :scope => @scope
- end
-
- %w{path group source schedule subscribe}.each do |param|
- assert_nothing_raised("Param %s was considered invalid" % param) do
- res.paramcheck(param)
- end
- end
-
- %w{this bad noness}.each do |param|
- assert_raise(Puppet::ParseError, "%s was considered valid" % param) do
- res.paramcheck(param)
- end
- end
+ # There are three cases here:
- # Now create a defined resource
- assert_nothing_raised do
- res = Parser::Resource.new :type => "resource", :title => "yay",
- :source => @source, :scope => @scope
- end
-
- %w{one two three schedule subscribe}.each do |param|
- assert_nothing_raised("Param %s was considered invalid" % param) do
- res.paramcheck(param)
- end
- end
-
- %w{this bad noness}.each do |param|
- assert_raise(Puppet::ParseError, "%s was considered valid" % param) do
- res.paramcheck(param)
- end
- end
+ # It's a valid parameter
+ res = mkresource
+ ref = mock('ref')
+ res.instance_variable_set("@ref", ref)
+ klass = mock("class")
+ ref.expects(:typeclass).returns(klass).times(4)
+ klass.expects(:validattr?).with("good").returns(true)
+ assert(res.send(:paramcheck, :good), "Did not allow valid param")
+
+ # It's name or title
+ klass.expects(:validattr?).with("name").returns(false)
+ assert(res.send(:paramcheck, :name), "Did not allow name")
+ klass.expects(:validattr?).with("title").returns(false)
+ assert(res.send(:paramcheck, :title), "Did not allow title")
+
+ # It's not actually allowed
+ klass.expects(:validattr?).with("other").returns(false)
+ res.expects(:fail)
+ ref.expects(:type)
+ res.send(:paramcheck, :other)
end
def test_to_trans
@@ -186,62 +235,10 @@ class TestResource < PuppetTest::TestCase
assert_equal(["file", refs[3].title], obj["notify"], "Array with single resource reference was not turned into single value")
end
- def test_adddefaults
- # Set some defaults at the top level
- top = {:one => "fun", :two => "shoe"}
-
- @scope.setdefaults("resource", paramify(@source, top))
-
- # Make a resource at that level
- res = Parser::Resource.new :type => "resource", :title => "yay",
- :source => @source, :scope => @scope
-
- # Add the defaults
- assert_nothing_raised do
- res.adddefaults
- end
-
- # And make sure we got them
- top.each do |p, v|
- assert_equal(v, res[p])
- end
-
- # Now got a bit lower
- other = @scope.newscope
-
- # And create a resource
- lowerres = Parser::Resource.new :type => "resource", :title => "funtest",
- :source => @source, :scope => other
-
- assert_nothing_raised do
- lowerres.adddefaults
- end
-
- # And check
- top.each do |p, v|
- assert_equal(v, lowerres[p])
- end
-
- # Now add some of our own defaults
- lower = {:one => "shun", :three => "free"}
- other.setdefaults("resource", paramify(@source, lower))
- otherres = Parser::Resource.new :type => "resource", :title => "yaytest",
- :source => @source, :scope => other
-
- should = top.dup
- # Make sure the lower defaults beat the higher ones.
- lower.each do |p, v| should[p] = v end
-
- otherres.adddefaults
-
- should.each do |p,v|
- assert_equal(v, otherres[p])
- end
- end
-
def test_evaluate
+ @parser = mkparser
# Make a definition that we know will, um, do something
- @interp.newdefine "evaltest",
+ @parser.newdefine "evaltest",
:arguments => [%w{one}, ["two", stringobj("755")]],
:code => resourcedef("file", "/tmp",
"owner" => varref("one"), "mode" => varref("two"))
@@ -272,49 +269,36 @@ class TestResource < PuppetTest::TestCase
"Evaluated resource was not deleted")
end
- def test_addoverrides
- # First create an override for an object that doesn't yet exist
- over1 = mkresource :source => "sub1", :params => {:one => "yay"}
-
- assert_nothing_raised do
- @scope.setoverride(over1)
- end
-
- assert(over1.override, "Override was not marked so")
-
- # Now make the resource
- res = mkresource :source => "base", :params => {:one => "rah",
- :three => "foo"}
-
- # And add it to our scope
- @scope.setresource(res)
-
- # And make sure over1 has not yet taken affect
- assert_equal("foo", res[:three], "Lost value")
-
- # Now add an immediately binding override
- over2 = mkresource :source => "sub1", :params => {:three => "yay"}
-
- assert_nothing_raised do
- @scope.setoverride(over2)
- end
-
- # And make sure it worked
- assert_equal("yay", res[:three], "Override 2 was ignored")
-
- # Now add our late-binding override
- assert_nothing_raised do
- res.addoverrides
- end
-
- # And make sure they're still around
- assert_equal("yay", res[:one], "Override 1 lost")
- assert_equal("yay", res[:three], "Override 2 lost")
-
- # And finally, make sure that there are no remaining overrides
- assert_nothing_raised do
- res.addoverrides
- end
+ def test_add_overrides
+ # Try it with nil
+ res = mkresource
+ res.scope = mock('scope')
+ config = mock("config")
+ res.scope.expects(:configuration).returns(config)
+ config.expects(:resource_overrides).with(res).returns(nil)
+ res.expects(:merge).never
+ res.send(:add_overrides)
+
+ # And an empty array
+ res = mkresource
+ res.scope = mock('scope')
+ config = mock("config")
+ res.scope.expects(:configuration).returns(config)
+ config.expects(:resource_overrides).with(res).returns([])
+ res.expects(:merge).never
+ res.send(:add_overrides)
+
+ # And with some overrides
+ res = mkresource
+ res.scope = mock('scope')
+ config = mock("config")
+ res.scope.expects(:configuration).returns(config)
+ returns = %w{a b}
+ config.expects(:resource_overrides).with(res).returns(returns)
+ res.expects(:merge).with("a")
+ res.expects(:merge).with("b")
+ res.send(:add_overrides)
+ assert(returns.empty?, "Did not clear overrides")
end
def test_proxymethods
@@ -326,28 +310,18 @@ class TestResource < PuppetTest::TestCase
assert_equal(false, res.builtin?)
end
- def test_addmetaparams
- mkevaltest @interp
- res = Parser::Resource.new :type => "evaltest", :title => "yay",
- :source => @source, :scope => @scope,
- :params => paramify(@source, :tag => "yay")
-
- assert_nil(res[:schedule], "Got schedule already")
- assert_nothing_raised do
- res.addmetaparams
- end
- @scope.setvar("schedule", "daily")
-
- # This is so we can test that it won't override already-set metaparams
- @scope.setvar("tag", "funtest")
+ def test_add_metaparams
+ res = mkresource
+ params = res.instance_variable_get("@params")
+ params[:a] = :b
+ Puppet::Type.expects(:eachmetaparam).multiple_yields(:a, :b, :c)
+ res.scope.expects(:lookupvar).with("b", false).returns(:something)
+ res.scope.expects(:lookupvar).with("c", false).returns(:undefined)
+ res.expects(:set_parameter).with(:b, :something)
- assert_nothing_raised do
- res.addmetaparams
- end
+ res.send(:add_metaparams)
- assert_equal("daily", res[:schedule], "Did not get metaparam")
- assert_equal("yay", res[:tag], "Overrode explicitly-set metaparam")
- assert_nil(res[:noop], "Got invalid metaparam")
+ assert_nil(params[:c], "A value was created somehow for an unset metaparam")
end
def test_reference_conversion
@@ -397,18 +371,19 @@ class TestResource < PuppetTest::TestCase
# #472. Really, this still isn't the best behaviour, but at least
# it's consistent with what we have elsewhere.
def test_defaults_from_parent_classes
+ @parser = mkparser
# Make a parent class with some defaults in it
- @interp.newclass("base",
+ @parser.newclass("base",
:code => defaultobj("file", :owner => "root", :group => "root")
)
# Now a mid-level class with some different values
- @interp.newclass("middle", :parent => "base",
+ @parser.newclass("middle", :parent => "base",
:code => defaultobj("file", :owner => "bin", :mode => "755")
)
# Now a lower class with its own defaults plus a resource
- @interp.newclass("bottom", :parent => "middle",
+ @parser.newclass("bottom", :parent => "middle",
:code => AST::ASTArray.new(:children => [
defaultobj("file", :owner => "adm", :recurse => "true"),
resourcedef("file", "/tmp/yayness", {})
@@ -435,17 +410,18 @@ class TestResource < PuppetTest::TestCase
# The second part of #539 - make sure resources pass the arguments
# correctly.
def test_title_with_definitions
- define = @interp.newdefine "yayness",
+ @parser = mkparser
+ define = @parser.newdefine "yayness",
:code => resourcedef("file", "/tmp",
"owner" => varref("name"), "mode" => varref("title"))
- klass = @interp.findclass("", "")
+ klass = @parser.findclass("", "")
should = {:name => :owner, :title => :mode}
[
{:name => "one", :title => "two"},
{:title => "three"},
].each do |hash|
- scope = mkscope :interp => @interp
+ scope = mkscope :parser => @parser
args = {:type => "yayness", :title => hash[:title],
:source => klass, :scope => scope}
if hash[:name]
@@ -487,7 +463,8 @@ class TestResource < PuppetTest::TestCase
# #643 - Make sure virtual defines result in virtual resources
def test_virtual_defines
- define = @interp.newdefine("yayness",
+ @parser = mkparser
+ define = @parser.newdefine("yayness",
:code => resourcedef("file", varref("name"),
"mode" => "644"))
diff --git a/test/language/scope.rb b/test/language/scope.rb
index f0feee156..bd90caa53 100755
--- a/test/language/scope.rb
+++ b/test/language/scope.rb
@@ -98,8 +98,8 @@ class TestScope < Test::Unit::TestCase
end
def test_lookupvar
- interp = mkinterp
- scope = mkscope :interp => interp
+ parser = mkparser
+ scope = mkscope :parser => parser
# first do the plain lookups
assert_equal("", scope.lookupvar("var"), "scope did not default to string")
@@ -111,7 +111,7 @@ class TestScope < Test::Unit::TestCase
assert_equal("yep", scope.lookupvar("var"), "did not retrieve value correctly")
# Now test the parent lookups
- subscope = mkscope :interp => interp
+ subscope = mkscope :parser => parser
subscope.parent = scope
assert_equal("", subscope.lookupvar("nope"), "scope did not default to string with parent")
assert_equal("", subscope.lookupvar("nope", true), "scope ignored usestring setting with parent")
@@ -129,12 +129,12 @@ class TestScope < Test::Unit::TestCase
end
def test_lookup_qualified_var
- interp = mkinterp
- scope = mkscope :interp => interp
+ parser = mkparser
+ scope = mkscope :parser => parser
scopes = {}
classes = ["", "one", "one::two", "one::two::three"].each do |name|
- klass = interp.newclass(name)
+ klass = parser.newclass(name)
klass.evaluate(:scope => scope)
scopes[name] = scope.class_scope(klass)
end
@@ -149,7 +149,7 @@ class TestScope < Test::Unit::TestCase
def test_declarative
# set to declarative
- top = mkscope(:declarative => true)
+ top = mkscope
sub = mkscope(:parent => top)
assert_nothing_raised {
@@ -166,93 +166,89 @@ class TestScope < Test::Unit::TestCase
}
end
- def test_notdeclarative
- # set to not declarative
- top = mkscope(:declarative => false)
- sub = mkscope(:parent => top)
+ def test_setdefaults
+ config = mkconfig
- assert_nothing_raised {
- top.setvar("test","value")
- }
- assert_nothing_raised {
- top.setvar("test","other")
- }
- assert_nothing_raised {
- sub.setvar("test","later")
- }
- assert_nothing_raised {
- sub.setvar("test","yayness")
- }
- end
+ scope = config.topscope
- def test_setdefaults
- interp, scope, source = mkclassframing
+ defaults = scope.instance_variable_get("@defaults")
- # The setdefaults method doesn't really check what we're doing,
- # so we're just going to use fake defaults here.
+ # First the case where there are no defaults and we pass a single param
+ param = stub :name => "myparam"
+ scope.setdefaults(:mytype, param)
+ assert_equal({"myparam" => param}, defaults[:mytype], "Did not set default correctly")
- # First do a simple local lookup
- params = paramify(source, :one => "fun", :two => "shoe")
- origshould = {}
- params.each do |p| origshould[p.name] = p end
- assert_nothing_raised do
- scope.setdefaults(:file, params)
- end
+ # Now the case where we pass in multiple parameters
+ param1 = stub :name => "one"
+ param2 = stub :name => "two"
+ scope.setdefaults(:newtype, [param1, param2])
+ assert_equal({"one" => param1, "two" => param2}, defaults[:newtype], "Did not set multiple defaults correctly")
- ret = nil
- assert_nothing_raised do
- ret = scope.lookupdefaults(:file)
+ # And the case where there's actually a conflict. Use the first default for this.
+ newparam = stub :name => "myparam"
+ assert_raise(Puppet::ParseError, "Allowed resetting of defaults") do
+ scope.setdefaults(:mytype, param)
end
+ assert_equal({"myparam" => param}, defaults[:mytype], "Replaced default even though there was a failure")
+ end
- assert_equal(origshould, ret)
+ def test_lookupdefaults
+ config = mkconfig
+ top = config.topscope
- # Now create a subscope and add some more params.
- newscope = scope.newscope
+ # Make a subscope
+ sub = config.newscope(top)
- newparams = paramify(source, :one => "shun", :three => "free")
- assert_nothing_raised {
- newscope.setdefaults(:file, newparams)
- }
+ topdefs = top.instance_variable_get("@defaults")
+ subdefs = sub.instance_variable_get("@defaults")
- # And make sure we get the appropriate ones back
- should = {}
- params.each do |p| should[p.name] = p end
- newparams.each do |p| should[p.name] = p end
+ # First add some defaults to our top scope
+ topdefs[:t1] = {:p1 => :p2, :p3 => :p4}
+ topdefs[:t2] = {:p5 => :p6}
- assert_nothing_raised do
- ret = newscope.lookupdefaults(:file)
- end
-
- assert_equal(should, ret)
+ # Then the sub scope
+ subdefs[:t1] = {:p1 => :p7, :p8 => :p9}
+ subdefs[:t2] = {:p5 => :p10, :p11 => :p12}
- # Make sure we still only get the originals from the top scope
- assert_nothing_raised do
- ret = scope.lookupdefaults(:file)
+ # Now make sure we get the correct list back
+ result = nil
+ assert_nothing_raised("Could not get defaults") do
+ result = sub.lookupdefaults(:t1)
end
+ assert_equal(:p9, result[:p8], "Did not get child defaults")
+ assert_equal(:p4, result[:p3], "Did not override parent defaults with child default")
+ assert_equal(:p7, result[:p1], "Did not get parent defaults")
+ end
- assert_equal(origshould, ret)
+ def test_parent
+ config = mkconfig
+ top = config.topscope
- # Now create another scope and make sure we only get the top defaults
- otherscope = scope.newscope
- assert_equal(origshould, otherscope.lookupdefaults(:file))
+ # Make a subscope
+ sub = config.newscope(top)
- # And make sure none of the scopes has defaults for other types
- [scope, newscope, otherscope].each do |sc|
- assert_equal({}, sc.lookupdefaults(:exec))
- end
+ assert_equal(top, sub.parent, "Did not find parent scope correctly")
+ assert_equal(top, sub.parent, "Did not find parent scope on second call")
+ end
+
+ def test_class_scope
+ config = mkconfig
+ scope = config.topscope
+ config.expects(:class_scope).with(:testing).returns(:myscope)
+ assert_equal(:myscope, scope.class_scope(:testing), "Did not pass back the results of config.class_scope")
end
- def test_strinterp
+ def test_strparser
# Make and evaluate our classes so the qualified lookups work
- interp = mkinterp
- klass = interp.newclass("")
- scope = mkscope(:interp => interp)
+ parser = mkparser
+ klass = parser.newclass("")
+ scope = mkscope(:parser => parser)
klass.evaluate(:scope => scope)
- klass = interp.newclass("one")
+ klass = parser.newclass("one")
klass.evaluate(:scope => scope)
- klass = interp.newclass("one::two")
+ klass = parser.newclass("one::two")
klass.evaluate(:scope => scope)
@@ -264,7 +260,7 @@ class TestScope < Test::Unit::TestCase
scopes = {"" => scope}
%w{one one::two one::two::three}.each do |name|
- klass = interp.newclass(name)
+ klass = parser.newclass(name)
klass.evaluate(:scope => scope)
scopes[name] = scope.class_scope(klass)
scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,''))
@@ -297,8 +293,8 @@ class TestScope < Test::Unit::TestCase
tests.each do |input, output|
assert_nothing_raised("Failed to scan %s" % input.inspect) do
- assert_equal(output, scope.strinterp(input),
- 'did not interpret %s correctly' % input.inspect)
+ assert_equal(output, scope.strparser(input),
+ 'did not parserret %s correctly' % input.inspect)
end
end
@@ -310,8 +306,8 @@ class TestScope < Test::Unit::TestCase
%w{d f h l w z}.each do |l|
string = "\\" + l
assert_nothing_raised do
- assert_equal(string, scope.strinterp(string),
- 'did not interpret %s correctly' % string)
+ assert_equal(string, scope.strparser(string),
+ 'did not parserret %s correctly' % string)
end
assert(logs.detect { |m| m.message =~ /Unrecognised escape/ },
@@ -321,7 +317,7 @@ class TestScope < Test::Unit::TestCase
end
def test_setclass
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
base = scope.findclass("base")
assert(base, "Could not find base class")
@@ -392,11 +388,11 @@ class TestScope < Test::Unit::TestCase
end
def test_includefunction
- interp = mkinterp
- scope = mkscope :interp => interp
+ parser = mkparser
+ scope = mkscope :parser => parser
- myclass = interp.newclass "myclass"
- otherclass = interp.newclass "otherclass"
+ myclass = parser.newclass "myclass"
+ otherclass = parser.newclass "otherclass"
function = Puppet::Parser::AST::Function.new(
:name => "include",
@@ -417,12 +413,12 @@ class TestScope < Test::Unit::TestCase
end
def test_definedfunction
- interp = mkinterp
+ parser = mkparser
%w{one two}.each do |name|
- interp.newdefine name
+ parser.newdefine name
end
- scope = mkscope :interp => interp
+ scope = mkscope :parser => parser
assert_nothing_raised {
%w{one two file user}.each do |type|
@@ -503,7 +499,7 @@ class TestScope < Test::Unit::TestCase
# Verify that we recursively mark as exported the results of collectable
# components.
def test_exportedcomponents
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
children = []
args = AST::ASTArray.new(
@@ -513,7 +509,7 @@ class TestScope < Test::Unit::TestCase
)
# Create a top-level component
- interp.newdefine "one", :arguments => [%w{arg}],
+ parser.newdefine "one", :arguments => [%w{arg}],
:code => AST::ASTArray.new(
:children => [
resourcedef("file", "/tmp", {"owner" => varref("arg")})
@@ -521,7 +517,7 @@ class TestScope < Test::Unit::TestCase
)
# And a component that calls it
- interp.newdefine "two", :arguments => [%w{arg}],
+ parser.newdefine "two", :arguments => [%w{arg}],
:code => AST::ASTArray.new(
:children => [
resourcedef("one", "ptest", {"arg" => varref("arg")})
@@ -529,7 +525,7 @@ class TestScope < Test::Unit::TestCase
)
# And then a third component that calls the second
- interp.newdefine "three", :arguments => [%w{arg}],
+ parser.newdefine "three", :arguments => [%w{arg}],
:code => AST::ASTArray.new(
:children => [
resourcedef("two", "yay", {"arg" => varref("arg")})
@@ -545,7 +541,7 @@ class TestScope < Test::Unit::TestCase
obj.evaluate :scope => scope
# And then evaluate it
- interp.evaliterate(scope)
+ parser.evaliterate(scope)
%w{file}.each do |type|
objects = scope.lookupexported(type)
@@ -585,9 +581,11 @@ Host <<||>>"
objects = nil
# We run it twice because we want to make sure there's no conflict
# if we pull it up from the database.
+ node = mknode
+ node.parameters = {"hostname" => node.name}
2.times { |i|
assert_nothing_raised {
- objects = interp.run("localhost", {"hostname" => "localhost"})
+ objects = interp.compile(node)
}
flat = objects.flatten
@@ -603,7 +601,7 @@ Host <<||>>"
# Make sure tags behave appropriately.
def test_tags
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
# First make sure we can only set legal tags
["an invalid tag", "-anotherinvalid", "bad*tag"].each do |tag|
@@ -637,58 +635,22 @@ Host <<||>>"
assert_equal((ptags + %w{onemore subscope}).sort, newscope.tags.sort)
end
- # Make sure we successfully translate objects
- def test_translate
- interp, scope, source = mkclassframing
-
- # Create a define that we'll be using
- interp.newdefine("wrapper", :code => AST::ASTArray.new(:children => [
- resourcedef("file", varref("name"), "owner" => "root")
- ]))
-
- # Now create a resource that uses that define
- define = mkresource(:type => "wrapper", :title => "/tmp/testing",
- :scope => scope, :source => source, :params => :none)
-
- scope.setresource define
-
- # And a normal resource
- scope.setresource mkresource(:type => "file", :title => "/tmp/rahness",
- :scope => scope, :source => source,
- :params => {:owner => "root"})
-
- # Evaluate the the define thing.
- define.evaluate
-
- # Now the scope should have a resource and a subscope. Translate the
- # whole thing.
- ret = nil
- assert_nothing_raised do
- ret = scope.translate
- end
-
- assert_instance_of(Puppet::TransBucket, ret)
-
- ret.each do |obj|
- assert(obj.is_a?(Puppet::TransBucket) || obj.is_a?(Puppet::TransObject),
- "Got a non-transportable object %s" % obj.class)
- end
-
- rahness = ret.find { |c| c.type == "file" and c.name == "/tmp/rahness" }
- assert(rahness, "Could not find top-level file")
- assert_equal("root", rahness["owner"])
-
- bucket = ret.find { |c| c.class == Puppet::TransBucket and c.name == "/tmp/testing" }
- assert(bucket, "Could not find define bucket")
+ # FIXME This isn't a great test, but I need to move on.
+ def test_to_trans
+ bucket = mock("transbucket")
+ Puppet::TransBucket.expects(:new).with([]).returns(bucket)
+ scope = mkscope
+ scope.type = "mytype"
+ scope.name = "myname"
- testing = bucket.find { |c| c.type == "file" and c.name == "/tmp/testing" }
- assert(testing, "Could not find define file")
- assert_equal("root", testing["owner"])
+ bucket.expects(:name=).with("myname")
+ bucket.expects(:type=).with("mytype")
+ scope.to_trans
end
def test_namespaces
- interp, scope, source = mkclassframing
+ parser, scope, source = mkclassframing
assert_equal([""], scope.namespaces,
"Started out with incorrect namespaces")
@@ -701,17 +663,17 @@ Host <<||>>"
end
def test_findclass_and_finddefine
- interp = mkinterp
+ parser = mkparser
- # Make sure our scope calls the interp findclass method with
+ # Make sure our scope calls the parser findclass method with
# the right namespaces
- scope = mkscope :interp => interp
+ scope = mkscope :parser => parser
- interp.metaclass.send(:attr_accessor, :last)
+ parser.metaclass.send(:attr_accessor, :last)
methods = [:findclass, :finddefine]
methods.each do |m|
- interp.meta_def(m) do |namespace, name|
+ parser.meta_def(m) do |namespace, name|
@checked ||= []
@checked << [namespace, name]
@@ -727,7 +689,7 @@ Host <<||>>"
end
test = proc do |should|
- interp.last = scope.namespaces[-1]
+ parser.last = scope.namespaces[-1]
methods.each do |method|
result = scope.send(method, "testing")
assert_equal(should, result,
diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb
index d66367ada..368e112f9 100644
--- a/test/lib/puppettest/parsertesting.rb
+++ b/test/lib/puppettest/parsertesting.rb
@@ -5,6 +5,8 @@ module PuppetTest::ParserTesting
include PuppetTest
AST = Puppet::Parser::AST
+ Config = Puppet::Parser::Configuration
+
# A fake class that we can use for testing evaluation.
class FakeAST
attr_writer :evaluate
@@ -39,6 +41,19 @@ module PuppetTest::ParserTesting
)
end
+ def mkconfig(parser = nil)
+ require 'puppet/network/handler/node'
+ parser ||= mkparser
+ node = mknode
+ return Config.new(parser, node)
+ end
+
+ def mknode(name = nil)
+ name ||= "nodename"
+ Puppet::Network::Handler.handler(:node)
+ Puppet::Network::Handler::Node::SimpleNode.new("nodename")
+ end
+
def mkinterp(args = {})
args[:Code] ||= "" unless args.include?(:Manifest)
args[:Local] ||= true
@@ -50,9 +65,9 @@ module PuppetTest::ParserTesting
end
def mkscope(hash = {})
- hash[:interp] ||= mkinterp
- hash[:source] ||= (hash[:interp].findclass("", "") ||
- hash[:interp].newclass(""))
+ hash[:configuration] ||= mkconfig
+ hash[:parser] ||= mkparser
+ hash[:source] ||= (hash[:parser].findclass("", "") || hash[:parser].newclass(""))
unless hash[:source]
raise "Could not find source for scope"
diff --git a/test/lib/puppettest/resourcetesting.rb b/test/lib/puppettest/resourcetesting.rb
index 8cb59b83d..cbcfb0baf 100644
--- a/test/lib/puppettest/resourcetesting.rb
+++ b/test/lib/puppettest/resourcetesting.rb
@@ -1,25 +1,25 @@
module PuppetTest::ResourceTesting
Parser = Puppet::Parser
AST = Puppet::Parser::AST
- def mkclassframing(interp = nil)
- interp ||= mkinterp
+ def mkclassframing(parser = nil)
+ parser ||= mkparser
- interp.newdefine("resource", :arguments => [%w{one}, %w{two value}, %w{three}])
- interp.newclass("")
- source = interp.newclass("base")
- interp.newclass("sub1", :parent => "base")
- interp.newclass("sub2", :parent => "base")
- interp.newclass("other")
+ parser.newdefine("resource", :arguments => [%w{one}, %w{two value}, %w{three}])
+ parser.newclass("")
+ source = parser.newclass("base")
+ parser.newclass("sub1", :parent => "base")
+ parser.newclass("sub2", :parent => "base")
+ parser.newclass("other")
- scope = Parser::Scope.new(:interp => interp)
- scope.source = source
+ config = mkconfig(:parser => parser)
+ config.topscope.source = source
- return interp, scope, source
+ return parser, config.topscope, source
end
- def mkevaltest(interp = nil)
- interp ||= mkinterp
- @interp.newdefine("evaltest",
+ def mkevaltest(parser = nil)
+ parser ||= mkparser
+ @parser.newdefine("evaltest",
:arguments => [%w{one}, ["two", stringobj("755")]],
:code => resourcedef("file", "/tmp",
"owner" => varref("one"), "mode" => varref("two"))
@@ -27,26 +27,14 @@ module PuppetTest::ResourceTesting
end
def mkresource(args = {})
-
- if args[:scope] and ! args[:source]
- args[:source] = args[:scope].source
- end
-
- unless args[:scope]
- unless defined? @scope
- raise "Must set @scope to mkresource"
- end
- end
+ args[:source] ||= "source"
+ args[:scope] ||= "scope"
{:type => "resource", :title => "testing",
- :source => @source, :scope => @scope}.each do |param, value|
+ :source => "source", :scope => "scope"}.each do |param, value|
args[param] ||= value
end
- unless args[:source].is_a?(Puppet::Parser::AST::HostClass)
- args[:source] = args[:scope].findclass(args[:source])
- end
-
params = args[:params] || {:one => "yay", :three => "rah"}
if args[:params] == :none
args.delete(:params)
diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb
index 08e17373b..9cf52b1cd 100755
--- a/test/network/handler/master.rb
+++ b/test/network/handler/master.rb
@@ -8,56 +8,6 @@ require 'puppet/network/handler/master'
class TestMaster < Test::Unit::TestCase
include PuppetTest::ServerTest
- # run through all of the existing test files and make sure everything
- # works
- def test_files
- count = 0
- textfiles { |file|
- Puppet.debug("parsing %s" % file)
- client = nil
- master = nil
-
- # create our master
- assert_nothing_raised() {
- # this is the default server setup
- master = Puppet::Network::Handler.master.new(
- :Manifest => file,
- :UseNodes => false,
- :Local => true
- )
- }
-
- # and our client
- assert_nothing_raised() {
- client = Puppet::Network::Client.master.new(
- :Master => master
- )
- }
-
- # pull our configuration a few times
- assert_nothing_raised() {
- client.getconfig
- stopservices
- Puppet::Type.allclear
- }
- assert_nothing_raised() {
- client.getconfig
- stopservices
- Puppet::Type.allclear
- }
- assert_nothing_raised() {
- client.getconfig
- stopservices
- Puppet::Type.allclear
- }
- # only test three files; that's plenty
- if count > 3
- break
- end
- count += 1
- }
- end
-
def test_defaultmanifest
textfiles { |file|
Puppet[:manifest] = file
@@ -166,30 +116,6 @@ class TestMaster < Test::Unit::TestCase
assert(FileTest.exists?(file2), "Second file %s does not exist" % file2)
end
- def test_addfacts
- master = nil
- file = mktestmanifest()
- # create our master
- assert_nothing_raised() {
- # this is the default server setup
- master = Puppet::Network::Handler.master.new(
- :Manifest => file,
- :UseNodes => false,
- :Local => true
- )
- }
-
- facts = {}
-
- assert_nothing_raised {
- master.addfacts(facts)
- }
-
- %w{serverversion servername serverip}.each do |fact|
- assert(facts.include?(fact), "Fact %s was not set" % fact)
- end
- end
-
# Make sure we're using the hostname as configured with :node_name
def test_hostname_in_getconfig
master = nil