diff options
| author | Luke Kanies <luke@reductivelabs.com> | 2010-01-29 20:57:21 -0600 |
|---|---|---|
| committer | test branch <puppet-dev@googlegroups.com> | 2010-02-17 06:50:53 -0800 |
| commit | 7089446697ad550c22012bc2b5572030727d67e1 (patch) | |
| tree | 40d160f11839fe6e20311186ded4e621d23e1242 | |
| parent | 4871c909cd28c82b64d0b62d8a27e62737d8733d (diff) | |
| download | puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.gz puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.xz puppet-7089446697ad550c22012bc2b5572030727d67e1.zip | |
Removing Resource::Reference classes
This commit is hopefully less messy than it
first appears, but it's certainly cross-cutting.
The reason for all of this is that we previously only
looked up builtin resource types from outside the parser,
but now that the defined resource types are available globally
via environments, we can push that lookup code to Resource.
Once we do that, however, we have to have environment and
namespace information in every resource.
Here I remove the Resource::Reference classes (except
the AST class), and use Resource instances instead. I
did this because the shared code between the two classes
got incredibly complicated, such that they should have had
a hierarchical relationship disallowed by their constants.
This complexity convinced me just to get rid of References
entirely.
I also make Puppet::Parser::Resource a subclass
of Puppet::Resource.
There are still broken tests in test/, but this was a big
enough commit I wanted to get it in.
Signed-off-by: Luke Kanies <luke@reductivelabs.com>
56 files changed, 842 insertions, 1696 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb index 2e531ad75..09ae531aa 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -153,7 +153,6 @@ end require 'puppet/type' require 'puppet/parser' require 'puppet/resource' -require 'puppet/resource/reference' require 'puppet/network' require 'puppet/ssl' require 'puppet/module' diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb index d222893b3..5da40b32f 100644 --- a/lib/puppet/parser/ast/resource.rb +++ b/lib/puppet/parser/ast/resource.rb @@ -14,7 +14,7 @@ class Resource < AST::ResourceReference # in the current scope. def evaluate(scope) # Evaluate all of the specified params. - paramobjects = @params.collect { |param| + paramobjects = params.collect { |param| param.safeevaluate(scope) } @@ -25,8 +25,6 @@ class Resource < AST::ResourceReference resource_titles = [resource_titles] end - resource_type = qualified_type(scope) - # We want virtual to be true if exported is true. We can't # just set :virtual => self.virtual in the initialization, # because sometimes the :virtual attribute is set *after* @@ -39,9 +37,7 @@ class Resource < AST::ResourceReference # many times. resource_titles.flatten.collect { |resource_title| exceptwrap :type => Puppet::ParseError do - resource = Puppet::Parser::Resource.new( - :type => resource_type, - :title => resource_title, + resource = Puppet::Parser::Resource.new(type, resource_title, :params => paramobjects, :file => self.file, :line => self.line, diff --git a/lib/puppet/parser/ast/resource_defaults.rb b/lib/puppet/parser/ast/resource_defaults.rb index 3fde7ade2..f0746ecf1 100644 --- a/lib/puppet/parser/ast/resource_defaults.rb +++ b/lib/puppet/parser/ast/resource_defaults.rb @@ -12,7 +12,7 @@ class Puppet::Parser::AST # object type. def evaluate(scope) # Use a resource reference to canonize the type - ref = Puppet::Resource::Reference.new(@type, "whatever") + ref = Puppet::Resource.new(@type, "whatever") type = ref.type params = @params.safeevaluate(scope) diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb index 5eac50982..2d4f7a871 100644 --- a/lib/puppet/parser/ast/resource_override.rb +++ b/lib/puppet/parser/ast/resource_override.rb @@ -36,9 +36,7 @@ class Puppet::Parser::AST resource = [resource] unless resource.is_a?(Array) resource = resource.collect do |r| - res = Puppet::Parser::Resource.new( - :type => r.type, - :title => r.title, + res = Puppet::Parser::Resource.new(r.type, r.title, :params => params, :file => file, :line => line, diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb index 794e505b8..8e09a8e3b 100644 --- a/lib/puppet/parser/ast/resource_reference.rb +++ b/lib/puppet/parser/ast/resource_reference.rb @@ -1,76 +1,23 @@ +require 'puppet/parser/ast' require 'puppet/parser/ast/branch' +require 'puppet/resource' -class Puppet::Parser::AST - # A reference to an object. Only valid as an rvalue. - class ResourceReference < AST::Branch - attr_accessor :title, :type - # Is the type a builtin type? - def builtintype?(type) - if typeklass = Puppet::Type.type(type) - return typeklass - else - return false - end - end - - def each - [@type,@title].flatten.each { |param| - #Puppet.debug("yielding param %s" % param) - yield param - } - end +class Puppet::Parser::AST::ResourceReference < Puppet::Parser::AST::Branch + attr_accessor :title, :type - # Evaluate our object, but just return a simple array of the type - # and name. - def evaluate(scope) - title = @title.safeevaluate(scope) - title = [title] unless title.is_a?(Array) - - if @type.to_s.downcase == "class" - resource_type = "class" - title = title.collect { |t| qualified_class(scope, t) } - else - resource_type = qualified_type(scope) - end - - title = title.collect { |t| Puppet::Parser::Resource::Reference.new( - :type => resource_type, :title => t - ) } - return title.pop if title.length == 1 - return title - end - - # Look up a fully qualified class name. - def qualified_class(scope, title) - # Look up the full path to the class - if classobj = scope.find_hostclass(title) - title = classobj.name - else - raise Puppet::ParseError, "Could not find class %s" % title - end - end - - # Look up a fully-qualified type. This method is - # also used in AST::Resource. - def qualified_type(scope, title = nil) - # We want a lower-case type. For some reason. - objtype = @type.downcase - unless builtintype?(objtype) - if dtype = scope.find_definition(objtype) - objtype = dtype.name - else - raise Puppet::ParseError, "Could not find resource type %s" % objtype - end - end - return objtype - end + # Evaluate our object, but just return a simple array of the type + # and name. + def evaluate(scope) + titles = Array(title.safeevaluate(scope)).collect { |t| Puppet::Resource.new(type, t, :namespaces => scope.namespaces) } + return titles.pop if titles.length == 1 + return titles + end - def to_s - if title.is_a?(ASTArray) - "#{type.to_s.capitalize}#{title}" - else - "#{type.to_s.capitalize}[#{title}]" - end + def to_s + if title.is_a?(Puppet::Parser::AST::ASTArray) + "#{type.to_s.capitalize}#{title}" + else + "#{type.to_s.capitalize}[#{title}]" end end end diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb index a6763c419..044518793 100644 --- a/lib/puppet/parser/collector.rb +++ b/lib/puppet/parser/collector.rb @@ -75,7 +75,7 @@ class Puppet::Parser::Collector @collected = {} # Canonize the type - @type = Puppet::Resource::Reference.new(type, "whatever").type + @type = Puppet::Resource.new(type, "whatever").type @equery = equery @vquery = vquery diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb index c669076bb..8e84f5a5b 100644 --- a/lib/puppet/parser/compiler.rb +++ b/lib/puppet/parser/compiler.rb @@ -275,9 +275,9 @@ class Puppet::Parser::Compiler # Find and evaluate our main object, if possible. def evaluate_main - @main = known_resource_types.find_hostclass("", "") || known_resource_types.add(Puppet::Resource::Type.new(:hostclass, "")) + @main = known_resource_types.find_hostclass([""], "") || known_resource_types.add(Puppet::Resource::Type.new(:hostclass, "")) @topscope.source = @main - @main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main) + @main_resource = Puppet::Parser::Resource.new("class", :main, :scope => @topscope, :source => @main) @topscope.resource = @main_resource @resources << @main_resource diff --git a/lib/puppet/parser/functions/defined.rb b/lib/puppet/parser/functions/defined.rb index 5ad74a79e..4d1d8c6fd 100644 --- a/lib/puppet/parser/functions/defined.rb +++ b/lib/puppet/parser/functions/defined.rb @@ -6,21 +6,21 @@ Puppet::Parser::Functions::newfunction(:defined, :type => :rvalue, :doc => "Dete (e.g., ``if defined(File['/tmp/myfile']) { ... }``). This function is unfortunately dependent on the parse order of the configuration when testing whether a resource is defined.") do |vals| result = false + vals = [vals] unless vals.is_a?(Array) vals.each do |val| case val when String - # For some reason, it doesn't want me to return from here. if Puppet::Type.type(val) or find_definition(val) or find_hostclass(val) result = true break end - when Puppet::Parser::Resource::Reference + when Puppet::Resource if findresource(val.to_s) result = true break end else - raise ArgumentError, "Invalid argument of type %s to 'defined'" % val.class + raise ArgumentError, "Invalid argument of type '#{val.class}' to 'defined'" end end result diff --git a/lib/puppet/parser/functions/require.rb b/lib/puppet/parser/functions/require.rb index 66d60b9ce..294484a2b 100644 --- a/lib/puppet/parser/functions/require.rb +++ b/lib/puppet/parser/functions/require.rb @@ -49,7 +49,7 @@ fail if used with earlier clients. # The 'obvious' way is just to add an edge in the catalog, # but that is considered a containment edge, not a dependency # edge, so it usually gets lost on the client. - ref = Puppet::Parser::Resource::Reference.new(:type => :class, :title => klass) + ref = Puppet::Resource.new(:class, klass) resource.set_parameter(:require, [resource[:require]].flatten.compact << ref) end end diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index e6bc46b86..d43b0d37d 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -388,15 +388,4 @@ class Puppet::Parser::Parser def watch_file(filename) known_resource_types.watch_file(filename) end - - private - - def check_and_add_to_watched_files(filename) - unless @files.include?(filename) - @files[filename] = Puppet::Util::LoadedFile.new(filename) - return true - else - return false - end - end end diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 428b9df50..36f1fbe93 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -1,8 +1,11 @@ -# A resource that we're managing. This handles making sure that only subclasses -# can set parameters. -class Puppet::Parser::Resource +require 'puppet/resource' + +# The primary difference between this class and its +# parent is that this class has rules on who can set +# parameters +class Puppet::Parser::Resource < Puppet::Resource require 'puppet/parser/resource/param' - require 'puppet/parser/resource/reference' + require 'puppet/resource' require 'puppet/util/tagging' require 'puppet/file_collection/lookup' require 'puppet/parser/yaml_trimmer' @@ -29,15 +32,8 @@ class Puppet::Parser::Resource @relationship_names.include?(name) end - # Proxy a few methods to our @ref object. - [:builtin?, :type, :title].each do |method| - define_method(method) do - @ref.send(method) - end - end - # Set up some boolean test methods - [:exported, :translated, :override, :virtual, :evaluated].each do |method| + [:translated, :override, :evaluated].each do |method| newmeth = (method.to_s + "?").intern define_method(newmeth) do self.send(method) @@ -60,25 +56,25 @@ class Puppet::Parser::Resource set_parameter(param, value) end - def builtin=(bool) - @ref.builtin = bool - end - def eachparam @params.each do |name, param| yield param end end + def environment + scope.environment + end + # Retrieve the associated definition and evaluate it. def evaluate - if klass = @ref.definedtype + if klass = resource_type and ! builtin_type? finish() return klass.evaluate_code(self) elsif builtin? - devfail "Cannot evaluate a builtin type" + devfail "Cannot evaluate a builtin type (#{type})" else - self.fail "Cannot find definition %s" % self.type + self.fail "Cannot find definition #{type}" end ensure @evaluated = true @@ -111,61 +107,41 @@ class Puppet::Parser::Resource defined?(@finished) and @finished end - def initialize(options) + def initialize(type, title, options) + self.type = type + self.title = title + + @params = {} + # Define all of the parameters + if params = options[:params] + extract_parameters(params) + options.delete(:params) + end + # 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) + else + raise ArgumentError, "Resources do not accept #{option}" end end unless self.scope raise ArgumentError, "Resources require a scope" end - @source ||= scope.source - - options = symbolize_options(options) - - # 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 - - @ref = Reference.new(:type => type, :title => title, :scope => self.scope) - - @params = {} - - # Define all of the parameters - if params = options[:params] - options.delete(:params) - params.each do |param| - # Don't set the same parameter twice - if @params[param.name] - self.fail Puppet::ParseError, "Duplicate parameter '%s' for on %s" % - [param.name, self.to_s] - end - - set_parameter(param) - end - end - # 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 + @source ||= scope.source - tag(@ref.type) - tag(@ref.title) if valid_tag?(@ref.title.to_s) + tag(self.type) + tag(self.title) if valid_tag?(self.title.to_s) end # Is this resource modeling an isomorphic resource type? def isomorphic? - if builtin? - return @ref.builtintype.isomorphic? + if builtin_type? + return resource_type.isomorphic? else return true end @@ -199,12 +175,8 @@ class Puppet::Parser::Resource @name end - # This *significantly* reduces the number of calls to Puppet.[]. - def paramcheck? - unless defined? @@paramcheck - @@paramcheck = Puppet[:paramcheck] - end - @@paramcheck + def namespaces + scope.namespaces end # A temporary occasion, until I get paths in the scopes figured out. @@ -212,11 +184,6 @@ class Puppet::Parser::Resource to_s end - # Return the short version of our name. - def ref - @ref.to_s - end - # Define a parameter in our resource. # if we ever receive a parameter named 'tag', set # the resource tags with its value. @@ -254,16 +221,16 @@ class Puppet::Parser::Resource result = Puppet::Resource.new(type, title) to_hash.each do |p, v| - if v.is_a?(Puppet::Parser::Resource::Reference) - v = Puppet::Resource::Reference.new(v.type, v.title) + if v.is_a?(Puppet::Resource) + v = Puppet::Resource.new(v.type, v.title) elsif v.is_a?(Array) # flatten resource references arrays - if v.flatten.find { |av| av.is_a?(Puppet::Parser::Resource::Reference) } + if v.flatten.find { |av| av.is_a?(Puppet::Resource) } v = v.flatten end v = v.collect do |av| - if av.is_a?(Puppet::Parser::Resource::Reference) - av = Puppet::Resource::Reference.new(av.type, av.title) + if av.is_a?(Puppet::Resource) + av = Puppet::Resource.new(av.type, av.title) end av end @@ -289,10 +256,6 @@ class Puppet::Parser::Resource return result end - def to_s - self.ref - end - # Translate our object to a transportable object. def to_trans return nil if virtual? @@ -389,28 +352,26 @@ class Puppet::Parser::Resource set_parameter(param) 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.valid_parameter?(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 - # 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) + validate_parameter(name) + end + rescue => detail + fail Puppet::ParseError, detail.to_s + end + + private + + def extract_parameters(params) + params.each do |param| + # Don't set the same parameter twice + if @params[param.name] + self.fail Puppet::ParseError, "Duplicate parameter '%s' for on %s" % + [param.name, self.to_s] + end + + set_parameter(param) end end end diff --git a/lib/puppet/parser/resource/reference.rb b/lib/puppet/parser/resource/reference.rb deleted file mode 100644 index ac1c79aef..000000000 --- a/lib/puppet/parser/resource/reference.rb +++ /dev/null @@ -1,103 +0,0 @@ -# A reference to a resource. Mostly just the type and title. -require 'puppet/resource/reference' -require 'puppet/file_collection/lookup' -require 'puppet/parser/yaml_trimmer' - -require 'puppet/resource/type_collection_helper' - -# A reference to a resource. Mostly just the type and title. -class Puppet::Parser::Resource::Reference < Puppet::Resource::Reference - include Puppet::Parser::YamlTrimmer - include Puppet::FileCollection::Lookup - include Puppet::Util::MethodHelper - include Puppet::Util::Errors - include Puppet::Resource::TypeCollectionHelper - - attr_accessor :builtin, :file, :line, :scope - - # Are we a builtin type? - def builtin? - unless defined? @builtin - if builtintype() - @builtin = true - else - @builtin = false - end - end - - @builtin - end - - def builtintype - if t = Puppet::Type.type(self.type.downcase) and t.name != :component - t - else - nil - end - end - - # Return the defined type for our obj. This can return classes, - # definitions or nodes. - def definedtype - unless defined? @definedtype - case self.type - when "Class" # look for host classes - name = self.title == :main ? "" : self.title - unless tmp = known_resource_types.find_hostclass("", name) - fail Puppet::ParseError, "Could not find '#{title}' class" - end - when "Node" # look for node definitions - unless tmp = known_resource_types.node(self.title) - fail Puppet::ParseError, "Could not find node '%s'" % self.title - end - else # normal definitions - # The resource type is capitalized, so we have to downcase. Really, - # we should have a better interface for finding these, but eh. - tmp = known_resource_types.definition(self.type.downcase) - end - - if tmp - @definedtype = tmp - else - fail Puppet::ParseError, "Could not find resource type '%s'" % self.type - end - end - - @definedtype - end - - def environment - scope.environment - end - - def initialize(hash) - set_options(hash) - requiredopts(:type, :title) - end - - def skip_for_yaml - %w{@typeclass @definedtype} - end - - def to_ref - # We have to return different cases to provide backward compatibility - # from 0.24.x to 0.23.x. - if builtin? - return [type.to_s.downcase, title.to_s] - else - return [type.to_s, title.to_s] - end - end - - def typeclass - unless defined? @typeclass - if tmp = builtintype || definedtype - @typeclass = tmp - else - fail Puppet::ParseError, "Could not find type %s" % self.type - end - end - - @typeclass - end -end diff --git a/lib/puppet/rails/param_value.rb b/lib/puppet/rails/param_value.rb index b298924f3..d0bb8d7d3 100644 --- a/lib/puppet/rails/param_value.rb +++ b/lib/puppet/rails/param_value.rb @@ -23,7 +23,7 @@ class Puppet::Rails::ParamValue < ActiveRecord::Base def self.munge_parser_values(value) values = value.is_a?(Array) ? value : [value] values.map do |v| - if v.is_a?(Puppet::Resource::Reference) + if v.is_a?(Puppet::Resource) v else v.to_s diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index 010cd956e..ec1fd2eae 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -5,7 +5,6 @@ require 'puppet/util/pson' # The simplest resource class. Eventually it will function as the # base class for all resource-like behaviour. class Puppet::Resource - require 'puppet/resource/reference' include Puppet::Util::Tagging require 'puppet/resource/type_collection_helper' @@ -13,8 +12,8 @@ class Puppet::Resource extend Puppet::Util::Pson include Enumerable - attr_accessor :file, :line, :catalog, :exported, :virtual, :namespace, :validate_parameters - attr_writer :type, :title, :environment + attr_accessor :file, :line, :catalog, :exported, :virtual, :validate_parameters + attr_reader :type, :title, :namespaces require 'puppet/indirector' extend Puppet::Indirector @@ -95,6 +94,13 @@ class Puppet::Resource @parameters[parameter_name(param)] end + def ==(other) + return false unless other.respond_to?(:title) and self.type == other.type and self.title == other.title + + return false unless to_hash == other.to_hash + true + end + # Compatibility method. def builtin? builtin_type? @@ -102,7 +108,7 @@ class Puppet::Resource # Is this a builtin resource type? def builtin_type? - @reference.builtin_type? + resource_type.is_a?(Class) end # Iterate over each param/value pair, as required for Enumerable. @@ -114,6 +120,23 @@ class Puppet::Resource super || @parameters.keys.include?( parameter_name(parameter) ) end + # These two methods are extracted into a Helper + # module, but file load order prevents me + # from including them in the class, and I had weird + # behaviour (i.e., sometimes it didn't work) when + # I directly extended each resource with the helper. + def environment + Puppet::Node::Environment.new(@environment) + end + + def environment=(env) + if env.is_a?(String) or env.is_a?(Symbol) + @environment = env + else + @environment = env.name + end + end + %w{exported virtual}.each do |m| define_method(m+"?") do self.send(m) @@ -121,14 +144,11 @@ class Puppet::Resource end # Create our resource. - def initialize(type, title, attributes = {}) - # Doing this, instead of including it in the class, - # is the only way I could get the load order to work - # here. - extend Puppet::Node::Environment::Helper + def initialize(type, title = nil, attributes = {}) + self.type, self.title = extract_type_and_title(type, title) @parameters = {} - @namespace = "" + @namespaces = [""] (attributes[:parameters] || {}).each do |param, value| self[param] = value @@ -139,15 +159,25 @@ class Puppet::Resource send(attr.to_s + "=", value) end - @reference = Puppet::Resource::Reference.new(type, title) - - tag(@reference.type) - tag(@reference.title) if valid_tag?(@reference.title) + tag(self.type) + tag(self.title) if valid_tag?(self.title) end - # Provide a reference to our resource in the canonical form. def ref - @reference.to_s + to_s + end + + # Find our resource. + def resolve + return catalog.resource(to_s) if catalog + return nil + end + + def title=(value) + if @type and klass = Puppet::Type.type(@type.to_s.downcase) + value = klass.canonicalize_ref(value) + end + @title = value end def resource_type @@ -159,16 +189,6 @@ class Puppet::Resource end end - # Get our title information from the reference, since it will canonize it for us. - def title - @reference.title - end - - # Get our type information from the reference, since it will canonize it for us. - def type - @reference.type - end - # Produce a simple hash of our parameters. def to_hash result = @parameters.dup @@ -179,7 +199,7 @@ class Puppet::Resource end def to_s - return ref + "#{type}[#{title}]" end # Convert our resource to Puppet code. @@ -211,7 +231,7 @@ class Puppet::Resource # Translate our object to a backward-compatible transportable object. def to_trans - if @reference.builtin_type? + if builtin_type? result = to_transobject else result = to_transbucket @@ -223,16 +243,20 @@ class Puppet::Resource return result end + def to_trans_ref + [type.to_s, title.to_s] + end + # Create an old-style TransObject instance, for builtin resource types. def to_transobject # Now convert to a transobject - result = Puppet::TransObject.new(@reference.title, @reference.type) + result = Puppet::TransObject.new(title, type) to_hash.each do |p, v| - if v.is_a?(Puppet::Resource::Reference) + if v.is_a?(Puppet::Resource) v = v.to_trans_ref elsif v.is_a?(Array) v = v.collect { |av| - if av.is_a?(Puppet::Resource::Reference) + if av.is_a?(Puppet::Resource) av = av.to_trans_ref end av @@ -266,6 +290,15 @@ class Puppet::Resource self end + # Canonize the type so we know it's always consistent. + def type=(value) + if value.nil? or value.to_s.downcase == "component" + @type = "Class" + else + @type = value.to_s.split("::").collect { |s| s.capitalize }.join("::") + end + end + def valid_parameter?(name) resource_type.valid_parameter?(name) end @@ -282,7 +315,7 @@ class Puppet::Resource def find_hostclass name = title == :main ? "" : title - known_resource_types.find_hostclass(namespace, name) + known_resource_types.find_hostclass(namespaces, name) end def find_builtin_resource_type @@ -290,7 +323,7 @@ class Puppet::Resource end def find_defined_resource_type - known_resource_types.find_definition(namespace, type.to_s.downcase) + known_resource_types.find_definition(namespaces, type.to_s.downcase) end # Produce a canonical method name. @@ -302,10 +335,14 @@ class Puppet::Resource param end + def namespaces=(ns) + @namespaces = Array(ns) + end + # The namevar for our resource type. If the type doesn't exist, # always use :name. def namevar - if t = resource_type + if builtin_type? and t = resource_type t.namevar else :name @@ -322,4 +359,14 @@ class Puppet::Resource # TransBuckets don't support parameters, which is why they're being deprecated. return bucket end + + private + + def extract_type_and_title(argtype, argtitle) + if (argtitle || argtype) =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ] + elsif argtitle then [ argtype, argtitle ] + elsif argtype.is_a?(Puppet::Type) then [ argtype.class.name, argtype.title ] + else raise ArgumentError, "No title provided and #{argtype.inspect} is not a valid resource reference" + end + end end diff --git a/lib/puppet/resource/catalog.rb b/lib/puppet/resource/catalog.rb index 6e064a9a1..e63c00c62 100644 --- a/lib/puppet/resource/catalog.rb +++ b/lib/puppet/resource/catalog.rb @@ -376,12 +376,12 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph # Always create a resource reference, so that it always canonizes how we # are referring to them. if title - ref = Puppet::Resource::Reference.new(type, title).to_s + ref = Puppet::Resource.new(type, title).to_s else # If they didn't provide a title, then we expect the first # argument to be of the form 'Class[name]', which our # Reference class canonizes for us. - ref = Puppet::Resource::Reference.new(nil, type).to_s + ref = Puppet::Resource.new(nil, type).to_s end @resource_table[ref] end diff --git a/lib/puppet/resource/reference.rb b/lib/puppet/resource/reference.rb deleted file mode 100644 index eddb2d96b..000000000 --- a/lib/puppet/resource/reference.rb +++ /dev/null @@ -1,90 +0,0 @@ -# -# Created by Luke Kanies on 2007-11-28. -# Copyright (c) 2007. All rights reserved. - -require 'puppet' -require 'puppet/resource' - -# A simple class to canonize how we refer to and retrieve -# resources. -class Puppet::Resource::Reference - attr_reader :type, :title - attr_accessor :catalog - - def ==(other) - other.respond_to?(:title) and self.type == other.type and self.title == other.title - end - - def builtin_type? - builtin_type ? true : false - end - - def initialize(argtype, argtitle = nil) - self.type,self.title = - if (argtitle || argtype) =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ] - elsif argtitle then [ argtype, argtitle ] - elsif argtype.is_a?(Puppet::Type) then [ argtype.class.name, argtype.title ] - else raise ArgumentError, "No title provided and #{argtype.inspect} is not a valid resource reference" - end - @builtin_type = nil - end - - # Find our resource. - def resolve - return catalog.resource(to_s) if catalog - return nil - end - - def title=(value) - if @type and klass = Puppet::Type.type(@type.to_s.downcase) - value = klass.canonicalize_ref(value) - end - @title = value - end - - # Canonize the type so we know it's always consistent. - def type=(value) - if value.nil? or value.to_s.downcase == "component" - @type = "Class" - else - # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] - x = @type = value.to_s.split("::").collect { |s| s.capitalize }.join("::") - end - - if @title - self.title = @title - end - end - - # Convert to the reference format that TransObject uses. Yay backward - # compatibility. - def to_trans_ref - # We have to return different cases to provide backward compatibility - # from 0.24.x to 0.23.x. - if builtin_type? - return [type.to_s.downcase, title.to_s] - else - return [type.to_s, title.to_s] - end - end - - # Convert to the standard way of referring to resources. - def to_s - "%s[%s]" % [@type, @title] - end - - private - - def builtin_type - if @builtin_type.nil? - if @type =~ /::/ - @builtin_type = false - elsif klass = Puppet::Type.type(@type.to_s.downcase) - @builtin_type = true - else - @builtin_type = false - end - end - @builtin_type - end -end diff --git a/lib/puppet/resource/type.rb b/lib/puppet/resource/type.rb index d47658284..c615a2ccb 100644 --- a/lib/puppet/resource/type.rb +++ b/lib/puppet/resource/type.rb @@ -60,11 +60,11 @@ class Puppet::Resource::Type # Add code from a new instance to our code. def merge(other) - fail ArgumentError, "#{name} is not a class; cannot add code to it" unless type == :hostclass - fail ArgumentError, "#{other.name} is not a class; cannot add code from it" unless other.type == :hostclass + fail "#{name} is not a class; cannot add code to it" unless type == :hostclass + fail "#{other.name} is not a class; cannot add code from it" unless other.type == :hostclass if parent and other.parent and parent != other.parent - fail ArgumentError, "Cannot merge classes with different parent classes" + fail "Cannot merge classes with different parent classes (#{name} => #{parent} vs. #{other.name} => #{other.parent})" end # We know they're either equal or only one is set, so keep whichever parent is specified. @@ -114,7 +114,7 @@ class Puppet::Resource::Type return resource end - resource = Puppet::Parser::Resource.new(:type => resource_type, :title => name, :scope => scope, :source => self) + resource = Puppet::Parser::Resource.new(resource_type, name, :scope => scope, :source => self) scope.compiler.add_resource(scope, resource) scope.catalog.tag(*resource.tags) resource diff --git a/lib/puppet/resource/type_collection.rb b/lib/puppet/resource/type_collection.rb index a0bd2ddf5..e2ca56290 100644 --- a/lib/puppet/resource/type_collection.rb +++ b/lib/puppet/resource/type_collection.rb @@ -1,6 +1,12 @@ class Puppet::Resource::TypeCollection attr_reader :environment + def clear + @hostclasses.clear + @definitions.clear + @nodes.clear + end + def initialize(env) @environment = env.is_a?(String) ? Puppet::Node::Environment.new(env) : env @hostclasses = {} @@ -19,6 +25,10 @@ class Puppet::Resource::TypeCollection end def add(instance) + if instance.type == :hostclass and other = @hostclasses[instance.name] and other.type == :hostclass + other.merge(instance) + return other + end method = "add_#{instance.type}" send(method, instance) instance.code_collection = self @@ -26,8 +36,8 @@ class Puppet::Resource::TypeCollection end def add_hostclass(instance) - dupe_check(instance, @hostclasses) { |dupe| "Class #{instance.name} is already defined#{dupe.error_context}; cannot redefine" } - dupe_check(instance, @definitions) { |dupe| "Definition #{instance.name} is already defined#{dupe.error_context}; cannot be redefined as a class" } + dupe_check(instance, @hostclasses) { |dupe| "Class '#{instance.name}' is already defined#{dupe.error_context}; cannot redefine" } + dupe_check(instance, @definitions) { |dupe| "Definition '#{instance.name}' is already defined#{dupe.error_context}; cannot be redefined as a class" } @hostclasses[instance.name] = instance instance @@ -38,7 +48,7 @@ class Puppet::Resource::TypeCollection end def add_node(instance) - dupe_check(instance, @nodes) { |dupe| "Node #{instance.name} is already defined#{dupe.error_context}; cannot redefine" } + dupe_check(instance, @nodes) { |dupe| "Node '#{instance.name}' is already defined#{dupe.error_context}; cannot redefine" } @node_list << instance @nodes[instance.name] = instance @@ -67,8 +77,10 @@ class Puppet::Resource::TypeCollection @nodes.length > 0 end - def add_definition(code) - @definitions[code.name] = code + def add_definition(instance) + dupe_check(instance, @hostclasses) { |dupe| "'#{instance.name}' is already defined#{dupe.error_context} as a class; cannot redefine as a definition" } + dupe_check(instance, @definitions) { |dupe| "Definition '#{instance.name}' is already defined#{dupe.error_context}; cannot be redefined" } + @definitions[instance.name] = instance end def definition(name) @@ -76,12 +88,13 @@ class Puppet::Resource::TypeCollection end def find(namespaces, name, type) + #Array("") == [] for some reason + namespaces = [namespaces] unless namespaces.is_a?(Array) + if r = find_fully_qualified(name, type) return r end - namespaces = Array(namespaces) - namespaces.each do |namespace| ary = namespace.split("::") diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb index 1970d9f1e..c4881701c 100644 --- a/lib/puppet/transportable.rb +++ b/lib/puppet/transportable.rb @@ -1,5 +1,5 @@ require 'puppet' -require 'puppet/resource/reference' +require 'puppet/resource' require 'yaml' module Puppet @@ -36,7 +36,7 @@ module Puppet def ref unless defined? @ref - @ref = Puppet::Resource::Reference.new(@type, @name) + @ref = Puppet::Resource.new(@type, @name) end @ref.to_s end @@ -225,11 +225,11 @@ module Puppet def to_ref unless defined? @ref if self.type and self.name - @ref = Puppet::Resource::Reference.new(self.type, self.name) + @ref = Puppet::Resource.new(self.type, self.name) elsif self.type and ! self.name # This is old-school node types - @ref = Puppet::Resource::Reference.new("node", self.type) + @ref = Puppet::Resource.new("node", self.type) elsif ! self.type and self.name - @ref = Puppet::Resource::Reference.new("component", self.name) + @ref = Puppet::Resource.new("component", self.name) else @ref = nil end @@ -244,7 +244,7 @@ module Puppet # Create a normalized resource from our TransObject. def to_resource params = defined?(@parameters) ? @parameters.dup : {} - Puppet::Resource.new(type, name, params) + Puppet::Resource.new(type, name, :parameters => params) end def param(param,value) diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 31728c374..ee545a99b 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -9,7 +9,7 @@ require 'puppet/metatype/manager' require 'puppet/util/errors' require 'puppet/util/log_paths' require 'puppet/util/logging' -require 'puppet/resource/reference' +require 'puppet/resource' require 'puppet/util/cacher' require 'puppet/file_collection/lookup' require 'puppet/util/tagging' @@ -1231,10 +1231,10 @@ class Type def munge(references) references = [references] unless references.is_a?(Array) references.collect do |ref| - if ref.is_a?(Puppet::Resource::Reference) + if ref.is_a?(Puppet::Resource) ref else - Puppet::Resource::Reference.new(ref) + Puppet::Resource.new(ref) end end end diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index bf9007ab4..d16cdda06 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -65,7 +65,7 @@ Puppet::Type.newtype(:component) do end def title=(str) - @reference = Puppet::Resource::Reference.new(str) + @reference = Puppet::Resource.new(str) end def refresh diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb index 830f47640..c912ad3ad 100755 --- a/lib/puppet/type/tidy.rb +++ b/lib/puppet/type/tidy.rb @@ -275,9 +275,9 @@ Puppet::Type.newtype(:tidy) do dir = File.dirname(path) next unless resource = files_by_name[dir] if resource[:require] - resource[:require] << Puppet::Resource::Reference.new(:file, path) + resource[:require] << Puppet::Resource.new(:file, path) else - resource[:require] = [Puppet::Resource::Reference.new(:file, path)] + resource[:require] = [Puppet::Resource.new(:file, path)] end end diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb index f50d46642..e3f95d89e 100644 --- a/lib/puppet/util/settings.rb +++ b/lib/puppet/util/settings.rb @@ -5,7 +5,6 @@ require 'puppet/external/event-loop' require 'puppet/util/cacher' require 'puppet/util/loadedfile' require 'puppet/resource' -require 'puppet/resource/reference' # The class for handling configuration files. class Puppet::Util::Settings diff --git a/spec/integration/application/puppet.rb b/spec/integration/application/puppet.rb index 1342f3c5f..cfafc9c0c 100755 --- a/spec/integration/application/puppet.rb +++ b/spec/integration/application/puppet.rb @@ -14,7 +14,7 @@ describe "Puppet" do it "should be able to apply catalogs provided in a file in pson" do file_to_create = tmpfile("pson_catalog") catalog = Puppet::Resource::Catalog.new - resource = Puppet::Resource.new(:file, file_to_create, :content => "my stuff") + resource = Puppet::Resource.new(:file, file_to_create, :parameters => {:content => "my stuff"}) catalog.add_resource resource manifest = tmpfile("manifest") diff --git a/spec/integration/indirector/catalog/compiler.rb b/spec/integration/indirector/catalog/compiler.rb index 16102cafe..b4067a6bb 100755 --- a/spec/integration/indirector/catalog/compiler.rb +++ b/spec/integration/indirector/catalog/compiler.rb @@ -8,6 +8,7 @@ Puppet::Resource::Catalog.indirection.terminus(:compiler) describe Puppet::Resource::Catalog::Compiler do before do + Facter.stubs(:value).returns "something" @catalog = Puppet::Resource::Catalog.new @one = Puppet::Resource.new(:file, "/one") diff --git a/spec/unit/configurer.rb b/spec/unit/configurer.rb index 9fc46affd..48a197a37 100755 --- a/spec/unit/configurer.rb +++ b/spec/unit/configurer.rb @@ -84,6 +84,7 @@ describe Puppet::Configurer, "when executing a catalog run" do before do Puppet.settings.stubs(:use).returns(true) @agent = Puppet::Configurer.new + @agent.stubs(:prepare) @agent.stubs(:facts_for_uploading).returns({}) @agent.stubs(:retrieve_catalog).returns Puppet::Resource::Catalog.new @@ -122,7 +123,7 @@ describe Puppet::Configurer, "when executing a catalog run" do it "should log a failure and do nothing if no catalog can be retrieved" do @agent.expects(:retrieve_catalog).returns nil - Puppet.expects(:err) + Puppet.expects(:err).with "Could not retrieve catalog; skipping run" @agent.run end diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb index d11daaa96..8339d1861 100755 --- a/spec/unit/indirector/catalog/compiler.rb +++ b/spec/unit/indirector/catalog/compiler.rb @@ -11,7 +11,7 @@ describe Puppet::Resource::Catalog::Compiler do before do Puppet::Rails.stubs(:init) Facter.stubs(:to_hash).returns({}) - Facter.stubs(:[]).returns(Facter::Util::Fact.new("something")) + Facter.stubs(:value).returns(Facter::Util::Fact.new("something")) end describe "when initializing" do @@ -44,7 +44,7 @@ describe Puppet::Resource::Catalog::Compiler do describe "and storeconfigs is enabled" do before do - Puppet.settings[:storeconfigs] = true + Puppet.settings.expects(:value).with(:storeconfigs).returns true end it "should initialize Rails if it is available" do @@ -141,11 +141,11 @@ describe Puppet::Resource::Catalog::Compiler do describe "when extracting facts from the request" do before do + Facter.stubs(:value).returns "something" @compiler = Puppet::Resource::Catalog::Compiler.new @request = stub 'request', :options => {} @facts = stub 'facts', :save => nil - Facter.stubs(:value).returns "something" end it "should do nothing if no facts are provided" do diff --git a/spec/unit/parser/ast/resource.rb b/spec/unit/parser/ast/resource.rb index b257cb116..391f4c770 100755 --- a/spec/unit/parser/ast/resource.rb +++ b/spec/unit/parser/ast/resource.rb @@ -9,16 +9,15 @@ describe Puppet::Parser::AST::Resource do @title = stub_everything 'title' @compiler = stub_everything 'compiler' @scope = Puppet::Parser::Scope.new(:compiler => @compiler) - @param1 = stub_everything 'parameter', :is_a? => true @scope.stubs(:resource).returns(stub_everything) - @params = ast::ASTArray.new( :children => [@param1]) - @resource = ast::Resource.new(:title => @title, :type => "Resource", :params => @params ) + @resource = ast::Resource.new(:title => @title, :type => "Resource", :params => ast::ASTArray.new(:children => []) ) @resource.stubs(:qualified_type).returns("Resource") - Puppet::Parser::Resource.stubs(:new).returns(stub_everything) end it "should evaluate all its parameters" do - @param1.expects(:safeevaluate).with(@scope) + param = stub 'param' + param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source")) + @resource.stubs(:params).returns [param] @resource.evaluate(@scope) end @@ -49,10 +48,10 @@ describe Puppet::Parser::AST::Resource do title_array.stubs(:flatten).returns([@title]) titles.stubs(:safeevaluate).with(@scope).returns(title_array) - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:title] == @title } - @resource.title = titles - @resource.evaluate(@scope) + result = @resource.evaluate(@scope) + result[0].should be_instance_of(Puppet::Parser::Resource) + result[0].title.should == @title end it "should handover resources to the compiler" do @@ -77,18 +76,18 @@ describe Puppet::Parser::AST::Resource do title_array.stubs(:flatten).returns([@title]) titles.stubs(:safeevaluate).with(@scope).returns(title_array) - Puppet::Parser::Resource.stubs(:new).returns(resource) - @compiler.stubs(:add_resource).with(resource) + @compiler.stubs(:add_resource) @resource.title = titles - @resource.evaluate(@scope).should == [resource] + @resource.evaluate(@scope)[0].should be_instance_of(Puppet::Parser::Resource) end it "should generate virtual resources if it is virtual" do @resource.virtual = true - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:virtual] == true } + result = @resource.evaluate(@scope) + result[0].should be_virtual @resource.evaluate(@scope) end @@ -96,8 +95,8 @@ describe Puppet::Parser::AST::Resource do it "should generate virtual and exported resources if it is exported" do @resource.exported = true - Puppet::Parser::Resource.expects(:new).with { |hash| hash[:virtual] == true and hash[:exported] == true } - - @resource.evaluate(@scope) + result = @resource.evaluate(@scope) + result[0].should be_virtual + result[0].should be_exported end end diff --git a/spec/unit/parser/ast/resource_reference.rb b/spec/unit/parser/ast/resource_reference.rb index 10d9678c3..ee42694b9 100755 --- a/spec/unit/parser/ast/resource_reference.rb +++ b/spec/unit/parser/ast/resource_reference.rb @@ -10,54 +10,31 @@ describe Puppet::Parser::AST::ResourceReference do @scope = Puppet::Parser::Scope.new() end - def newref(title, type) + def newref(type, title) title = stub 'title', :safeevaluate => title ref = Puppet::Parser::AST::ResourceReference.new(:type => type, :title => title) end - it "should evaluate correctly reference to builtin types" do - newref("/tmp/yay", "File").evaluate(@scope).to_s.should == "File[/tmp/yay]" + it "should correctly produce reference strings" do + newref("File", "/tmp/yay").evaluate(@scope).to_s.should == "File[/tmp/yay]" end - %{ "one::two" "one-two"}.each do |type| - it "should evaluate correctly reference to define" do - klass = stub 'klass', :title => "three", :name => type - @scope.stubs(:find_definition).returns(klass) - - newref("three", type).evaluate(@scope).to_ref.should == Puppet::Parser::Resource::Reference.new( :type => type, :title => "three" ).to_ref - end + it "should produce a single resource when the title evaluates to a string" do + newref("File", "/tmp/yay").evaluate(@scope).should == Puppet::Resource.new("file", "/tmp/yay") end - it "should be able to call qualified_class" do - klass = stub 'klass', :title => "three", :name => "one" - @scope.expects(:find_hostclass).with("one").returns(klass) - newref("three","class").qualified_class(@scope,"one").should == "one" - end - - it "should be able to find qualified classes when evaluating" do - klass = stub 'klass', :title => "one", :name => "one" - @scope.stubs(:find_hostclass).returns(klass) - - evaled = newref("one", "class").evaluate(@scope) - evaled.type.should == "Class" - evaled.title.should == "one" - end - - it "should return an array of reference if given an array of titles" do + it "should return an array of resources if given an array of titles" do titles = mock 'titles', :safeevaluate => ["title1","title2"] - ref = ast::ResourceReference.new( :title => titles, :type => "Resource" ) - ref.stubs(:qualified_type).with(@scope).returns("Resource") - - ref.evaluate(@scope).should have(2).elements + ref = ast::ResourceReference.new( :title => titles, :type => "File" ) + ref.evaluate(@scope).should == [ + Puppet::Resource.new("file", "title1"), + Puppet::Resource.new("file", "title2") + ] end - it "should qualify class of all titles for Class resource references" do - titles = mock 'titles', :safeevaluate => ["title1","title2"] - ref = ast::ResourceReference.new( :title => titles, :type => "Class" ) - ref.expects(:qualified_class).with(@scope,"title1").returns("class") - ref.expects(:qualified_class).with(@scope,"title2").returns("class") - - ref.evaluate(@scope) + it "should pass its scope's namespaces to all created resource references" do + @scope.add_namespace "foo" + newref("File", "/tmp/yay").evaluate(@scope).namespaces.should == ["foo"] end it "should return a correct representation when converting to string" do diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/collector.rb index 7f88bf754..9c2d722e5 100755 --- a/spec/unit/parser/collector.rb +++ b/spec/unit/parser/collector.rb @@ -52,11 +52,10 @@ end describe Puppet::Parser::Collector, "when collecting specific virtual resources" do before do @scope = mock 'scope' - @resource_type = mock 'resource_type' @vquery = mock 'vquery' @equery = mock 'equery' - @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, :virtual) + @collector = Puppet::Parser::Collector.new(@scope, "resource_type", @equery, @vquery, :virtual) end it "should not fail when it does not find any resources to collect" do diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb index 333046c77..6fd4d1fb5 100755 --- a/spec/unit/parser/compiler.rb +++ b/spec/unit/parser/compiler.rb @@ -174,10 +174,9 @@ describe Puppet::Parser::Compiler do it "should evaluate the main class if it exists" do compile_stub(:evaluate_main) - main_class = mock 'main_class' + main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "") main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } @compiler.topscope.expects(:source=).with(main_class) - @known_resource_types.stubs(:find_hostclass).with("", "").returns(main_class) @compiler.compile end @@ -185,7 +184,7 @@ describe Puppet::Parser::Compiler do it "should create a new, empty 'main' if no main class exists" do compile_stub(:evaluate_main) @compiler.compile - @known_resource_types.find_hostclass("", "").should be_instance_of(Puppet::Resource::Type) + @known_resource_types.find_hostclass([""], "").should be_instance_of(Puppet::Resource::Type) end it "should evaluate any node classes" do @@ -252,7 +251,7 @@ describe Puppet::Parser::Compiler do it "should call finish() on all resources" do # Add a resource that does respond to :finish - resource = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish" + resource = Puppet::Parser::Resource.new "file", "finish", :scope => @scope resource.expects(:finish) @compiler.add_resource(@scope, resource) @@ -268,12 +267,12 @@ describe Puppet::Parser::Compiler do it "should call finish() in add_resource order" do resources = sequence('resources') - resource1 = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish1" + resource1 = Puppet::Parser::Resource.new "file", "finish1", :scope => @scope resource1.expects(:finish).in_sequence(resources) @compiler.add_resource(@scope, resource1) - resource2 = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish2" + resource2 = Puppet::Parser::Resource.new "file", "finish2", :scope => @scope resource2.expects(:finish).in_sequence(resources) @compiler.add_resource(@scope, resource2) diff --git a/spec/unit/parser/functions/defined.rb b/spec/unit/parser/functions/defined.rb new file mode 100755 index 000000000..0da8c4a31 --- /dev/null +++ b/spec/unit/parser/functions/defined.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe "the 'defined' function" do + + before :each do + @scope = Puppet::Parser::Scope.new() + @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) + @scope.compiler = @compiler + end + + it "should exist" do + Puppet::Parser::Functions.function("defined").should == "function_defined" + end + + it "should be true when the name is defined as a class" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:hostclass, "yayness") + @scope.function_defined("yayness").should be_true + end + + it "should be true when the name is defined as a definition" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "yayness") + @scope.function_defined("yayness").should be_true + end + + it "should be true when the name is defined as a builtin type" do + @scope.function_defined("file").should be_true + end + + + it "should be true when any of the provided names are defined" do + @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "yayness") + @scope.function_defined(["meh", "yayness", "booness"]).should be_true + end + + it "should be false when a single given name is not defined" do + @scope.function_defined("meh").should be_false + end + + it "should be false when none of the names are defined" do + @scope.function_defined(["meh", "yayness", "booness"]).should be_false + end + + it "should be true when a resource reference is provided and the resource is in the catalog" do + resource = Puppet::Resource.new("file", "/my/file") + @compiler.add_resource(@scope, resource) + @scope.function_defined(resource).should be_true + end +end diff --git a/spec/unit/parser/functions/require.rb b/spec/unit/parser/functions/require.rb index 924990a5d..1d9ce931c 100755 --- a/spec/unit/parser/functions/require.rb +++ b/spec/unit/parser/functions/require.rb @@ -28,7 +28,7 @@ describe "the require function" do end it "should set the 'require' prarameter on the resource to a resource reference" do - @resource.expects(:set_parameter).with { |name, value| name == :require and value[0].is_a?(Puppet::Parser::Resource::Reference) } + @resource.expects(:set_parameter).with { |name, value| name == :require and value[0].is_a?(Puppet::Resource) } @scope.stubs(:function_include) @scope.function_require("myclass") end diff --git a/spec/unit/parser/functions/tag.rb b/spec/unit/parser/functions/tag.rb new file mode 100755 index 000000000..5fb467e59 --- /dev/null +++ b/spec/unit/parser/functions/tag.rb @@ -0,0 +1,24 @@ +#! /usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe "the 'tag' function" do + + before :each do + @scope = Puppet::Parser::Scope.new() + end + + it "should exist" do + Puppet::Parser::Functions.function(:tag).should == "function_tag" + end + + it "should tag the resource with any provided tags" do + resource = Puppet::Parser::Resource.new(:file, "/file", :scope => @scope) + @scope.expects(:resource).returns resource + + @scope.function_tag ["one", "two"] + + resource.should be_tagged("one") + resource.should be_tagged("two") + end +end diff --git a/spec/unit/parser/parser.rb b/spec/unit/parser/parser.rb index 84749c3fb..8cc29c9b8 100755 --- a/spec/unit/parser/parser.rb +++ b/spec/unit/parser/parser.rb @@ -429,6 +429,12 @@ describe Puppet::Parser do @krt.hostclass("foobar").parent.should == "yayness" end + it "should correctly set the parent class for multiple classes at a time" do + @parser.parse("class foobar inherits yayness {}\nclass boo inherits bar {}") + @krt.hostclass("foobar").parent.should == "yayness" + @krt.hostclass("boo").parent.should == "bar" + end + it "should define the code when some is provided" do @parser.parse("class foobar { $var = val }") @krt.hostclass("foobar").code.should_not be_nil @@ -451,5 +457,15 @@ describe Puppet::Parser do @krt.add(Puppet::Resource::Type.new(:hostclass, "foobar", :arguments => {"biz" => nil})) lambda { @parser.parse("class { foobar: biz => stuff }") }.should_not raise_error end + + it "should correctly mark exported resources as exported" do + @parser.parse("@@file { '/file': }") + @krt.hostclass("").code[0].exported.should be_true + end + + it "should correctly mark virtual resources as virtual" do + @parser.parse("@file { '/file': }") + @krt.hostclass("").code[0].virtual.should be_true + end end end diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb index bb3001c8e..0c70c817e 100755 --- a/spec/unit/parser/resource.rb +++ b/spec/unit/parser/resource.rb @@ -19,7 +19,7 @@ describe Puppet::Parser::Resource do args[:source] ||= "source" args[:scope] ||= stub('scope', :source => mock('source')) - {:type => "resource", :title => "testing", :source => "source", :scope => "scope"}.each do |param, value| + {:source => "source", :scope => "scope"}.each do |param, value| args[param] ||= value end @@ -30,7 +30,7 @@ describe Puppet::Parser::Resource do args[:params] = paramify(args[:source], params) end - Puppet::Parser::Resource.new(args) + Puppet::Parser::Resource.new("resource", "testing", args) end def param(name, value, source) @@ -61,19 +61,31 @@ describe Puppet::Parser::Resource do Puppet::Parser::Resource.ancestors.should be_include(Puppet::FileCollection::Lookup) end + it "should get its environment from its scope" do + scope = stub 'scope', :source => stub("source") + scope.expects(:environment).returns "foo" + Puppet::Parser::Resource.new("file", "whatever", :scope => scope).environment.should == "foo" + end + + it "should get its namespaces from its scope" do + scope = stub 'scope', :source => stub("source") + scope.expects(:namespaces).returns %w{one two} + Puppet::Parser::Resource.new("file", "whatever", :scope => scope).namespaces.should == %w{one two} + end + it "should be isomorphic if it is builtin and models an isomorphic type" do Puppet::Type.type(:file).expects(:isomorphic?).returns(true) - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true end it "should not be isomorphic if it is builtin and models a non-isomorphic type" do Puppet::Type.type(:file).expects(:isomorphic?).returns(false) - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_false + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_false end it "should be isomorphic if it is not builtin" do newdefine "whatever" - @resource = Puppet::Parser::Resource.new(:type => "whatever", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true + @resource = Puppet::Parser::Resource.new("whatever", "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true end it "should have a array-indexing method for retrieving parameter values" do @@ -89,77 +101,68 @@ describe Puppet::Parser::Resource do end it "should be able to use the indexing operator to access parameters" do - resource = Puppet::Parser::Resource.new(:type => "resource", :title => "testing", :source => "source", :scope => "scope") + resource = Puppet::Parser::Resource.new("resource", "testing", :source => "source", :scope => "scope") resource["foo"] = "bar" resource["foo"].should == "bar" end it "should return the title when asked for a parameter named 'title'" do - Puppet::Parser::Resource.new(:type => "resource", :title => "testing", :source => "source", :scope => "scope")[:title].should == "testing" + Puppet::Parser::Resource.new("resource", "testing", :source => "source", :scope => "scope")[:title].should == "testing" end describe "when initializing" do before do - @arguments = {:type => "resource", :title => "testing", :scope => stub('scope', :source => mock('source'))} + @arguments = {:scope => stub('scope', :source => mock('source'))} end - [:type, :title, :scope].each do |name| - it "should fail unless #{name.to_s} is specified" do - try = @arguments.dup - try.delete(name) - lambda { Puppet::Parser::Resource.new(try) }.should raise_error(ArgumentError) - end + it "should fail unless #{name.to_s} is specified" do + lambda { Puppet::Parser::Resource.new('file', '/my/file') }.should raise_error(ArgumentError) end it "should set the reference correctly" do - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("resource", "testing", @arguments) res.ref.should == "Resource[testing]" end it "should be tagged with user tags" do tags = [ "tag1", "tag2" ] @arguments[:params] = [ param(:tag, tags , :source) ] - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("resource", "testing", @arguments) (res.tags & tags).should == tags end end describe "when refering to a resource with name canonicalization" do before do - @arguments = {:type => "file", :title => "/path/", :scope => stub('scope', :source => mock('source'))} + @arguments = {:scope => stub('scope', :source => mock('source'))} end it "should canonicalize its own name" do - res = Puppet::Parser::Resource.new(@arguments) + res = Puppet::Parser::Resource.new("file", "/path/", @arguments) res.ref.should == "File[/path]" end end describe "when evaluating" do - before do - @type = Puppet::Parser::Resource - - @definition = newdefine "mydefine" - @class = newclass "myclass" - @nodedef = newnode("mynode") - end - it "should evaluate the associated AST definition" do - res = @type.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source) - @definition.expects(:evaluate_code).with(res) + definition = newdefine "mydefine" + res = Puppet::Parser::Resource.new("mydefine", "whatever", :scope => @scope, :source => @source) + definition.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST class" do - res = @type.new(:type => "class", :title => "myclass", :scope => @scope, :source => @source) + @class = newclass "myclass" + res = Puppet::Parser::Resource.new("class", "myclass", :scope => @scope, :source => @source) @class.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST node" do - res = @type.new(:type => "node", :title => "mynode", :scope => @scope, :source => @source) - @nodedef.expects(:evaluate_code).with(res) + nodedef = newnode("mynode") + res = Puppet::Parser::Resource.new("node", "mynode", :scope => @scope, :source => @source) + nodedef.expects(:evaluate_code).with(res) res.evaluate end end @@ -169,7 +172,7 @@ describe Puppet::Parser::Resource do @class = newclass "myclass" @nodedef = newnode("mynode") - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source) + @resource = Puppet::Parser::Resource.new("file", "whatever", :scope => @scope, :source => @source) end it "should do nothing if it has already been finished" do @@ -292,7 +295,7 @@ describe Puppet::Parser::Resource do before do @scope_resource = stub 'scope_resource', :tags => %w{srone srtwo} @scope = stub 'scope', :resource => @scope_resource - @resource = Puppet::Parser::Resource.new(:type => "file", :title => "yay", :scope => @scope, :source => mock('source')) + @resource = Puppet::Parser::Resource.new("file", "yay", :scope => @scope, :source => mock('source')) end it "should get tagged with the resource type" do @@ -304,19 +307,19 @@ describe Puppet::Parser::Resource do end it "should get tagged with each name in the title if the title is a qualified class name" do - resource = Puppet::Parser::Resource.new(:type => "file", :title => "one::two", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("file", "one::two", :scope => @scope, :source => mock('source')) resource.tags.should be_include("one") resource.tags.should be_include("two") end it "should get tagged with each name in the type if the type is a qualified class name" do - resource = Puppet::Parser::Resource.new(:type => "one::two", :title => "whatever", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("one::two", "whatever", :scope => @scope, :source => mock('source')) resource.tags.should be_include("one") resource.tags.should be_include("two") end it "should not get tagged with non-alphanumeric titles" do - resource = Puppet::Parser::Resource.new(:type => "file", :title => "this is a test", :scope => @scope, :source => mock('source')) + resource = Puppet::Parser::Resource.new("file", "this is a test", :scope => @scope, :source => mock('source')) resource.tags.should_not be_include("this is a test") end @@ -496,26 +499,26 @@ describe Puppet::Parser::Resource do @parser_resource.to_resource.virtual.should be_true end - it "should convert any parser resource references to Puppet::Resource::Reference instances" do - ref = Puppet::Parser::Resource::Reference.new(:title => "/my/file", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances" do + ref = Puppet::Resource.new("file", "/my/file") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ref} result = @parser_resource.to_resource - result[:fee].should == Puppet::Resource::Reference.new(:file, "/my/file") + result[:fee].should == Puppet::Resource.new(:file, "/my/file") end - it "should convert any parser resource references to Puppet::Resource::Reference instances even if they are in an array" do - ref = Puppet::Parser::Resource::Reference.new(:title => "/my/file", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances even if they are in an array" do + ref = Puppet::Resource.new("file", "/my/file") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ["a", ref]} result = @parser_resource.to_resource - result[:fee].should == ["a", Puppet::Resource::Reference.new(:file, "/my/file")] + result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file")] end - it "should convert any parser resource references to Puppet::Resource::Reference instances even if they are in an array of array, and even deeper" do - ref1 = Puppet::Parser::Resource::Reference.new(:title => "/my/file1", :type => "file") - ref2 = Puppet::Parser::Resource::Reference.new(:title => "/my/file2", :type => "file") + it "should convert any parser resource references to Puppet::Resource instances even if they are in an array of array, and even deeper" do + ref1 = Puppet::Resource.new("file", "/my/file1") + ref2 = Puppet::Resource.new("file", "/my/file2") @parser_resource = mkresource :source => @source, :params => {:foo => "bar", :fee => ["a", [ref1,ref2]]} result = @parser_resource.to_resource - result[:fee].should == ["a", Puppet::Resource::Reference.new(:file, "/my/file1"), Puppet::Resource::Reference.new(:file, "/my/file2")] + result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file1"), Puppet::Resource.new(:file, "/my/file2")] end it "should fail if the same param is declared twice" do @@ -531,4 +534,52 @@ describe Puppet::Parser::Resource do end.should raise_error(Puppet::ParseError) end end + + describe "when validating" do + it "should check each parameter" do + resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => stub("source") + resource[:one] = :two + resource[:three] = :four + resource.expects(:validate_parameter).with(:one) + resource.expects(:validate_parameter).with(:three) + resource.send(:validate) + end + + it "should raise a parse error when there's a failure" do + resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => stub("source") + resource[:one] = :two + resource.expects(:validate_parameter).with(:one).raises ArgumentError + lambda { resource.send(:validate) }.should raise_error(Puppet::ParseError) + end + end + + describe "when setting parameters" do + before do + @source = newclass "foobar" + @resource = Puppet::Parser::Resource.new :foo, "bar", :scope => stub("scope"), :source => @source + end + + it "should accept Param instances and add them to the parameter list" do + param = Puppet::Parser::Resource::Param.new :name => "foo", :value => "bar", :source => @source + @resource.set_parameter(param) + @resource["foo"].should == "bar" + end + + it "should fail when provided a parameter name but no value" do + lambda { @resource.set_parameter("myparam") }.should raise_error(ArgumentError) + end + + it "should use its source when provided a parameter name and value" do + @resource.set_parameter("myparam", "myvalue") + @resource["myparam"].should == "myvalue" + end + end + + # part of #629 -- the undef keyword. Make sure 'undef' params get skipped. + it "should not include 'undef' parameters when converting itself to a hash" do + resource = Puppet::Parser::Resource.new "file", "/tmp/testing", :source => mock("source"), :scope => mock("scope") + resource[:owner] = :undef + resource[:mode] = "755" + resource.to_hash[:owner].should be_nil + end end diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb deleted file mode 100755 index a38604226..000000000 --- a/spec/unit/parser/resource/reference.rb +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -describe Puppet::Parser::Resource::Reference do - before do - @type = Puppet::Parser::Resource::Reference - end - - it "should get its environment from its scope" do - env = stub 'environment' - scope = stub 'scope', :environment => env - @type.new(:title => "foo", :type => "bar", :scope => scope).environment.should equal(env) - end - - it "should use the resource type collection helper to find its known resource types" do - Puppet::Parser::Resource::Reference.ancestors.should include(Puppet::Resource::TypeCollectionHelper) - end - - it "should use the file lookup module" do - Puppet::Parser::Resource::Reference.ancestors.should be_include(Puppet::FileCollection::Lookup) - end - - it "should require a type" do - proc { @type.new(:title => "yay") }.should raise_error(Puppet::DevError) - end - - it "should require a title" do - proc { @type.new(:type => "file") }.should raise_error(Puppet::DevError) - end - - it "should know when it refers to a builtin type" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.builtin?.should be_true - ref.builtintype.should equal(Puppet::Type.type(:file)) - end - - it "should return a downcased relationship-style resource reference for defined types" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.to_ref.should == ["file", "/tmp/yay"] - end - - it "should return a capitalized relationship-style resource reference for defined types" do - ref = @type.new(:type => "whatever", :title => "/tmp/yay") - ref.to_ref.should == ["Whatever", "/tmp/yay"] - end - - it "should return a resource reference string when asked" do - ref = @type.new(:type => "file", :title => "/tmp/yay") - ref.to_s.should == "File[/tmp/yay]" - end - - it "should canonize resource reference types" do - ref = @type.new(:type => "foo::bar", :title => "/tmp/yay") - ref.to_s.should == "Foo::Bar[/tmp/yay]" - end - - it "should canonize resource reference values" do - ref = @type.new(:type => "file", :title => "/tmp/yay/") - ref.to_s.should == "File[/tmp/yay]" - end - - it "should canonize resource reference values without order dependencies" do - args = [[:title, "/tmp/yay/"], [:type, "file"]] - ref = @type.new(args) - ref.to_s.should == "File[/tmp/yay]" - end - -end - -describe Puppet::Parser::Resource::Reference, " when modeling defined types" do - def newclass(name) - @known_resource_types.add Puppet::Resource::Type.new(:hostclass, name) - end - - def newdefine(name) - @known_resource_types.add Puppet::Resource::Type.new(:definition, name) - end - - def newnode(name) - @known_resource_types.add Puppet::Resource::Type.new(:node, name) - end - - before do - @type = Puppet::Parser::Resource::Reference - - @known_resource_types = Puppet::Resource::TypeCollection.new("myenv") - @definition = newdefine("mydefine") - @class = newclass("myclass") - @nodedef = newnode("mynode") - @node = Puppet::Node.new("yaynode") - - @compiler = Puppet::Parser::Compiler.new(@node) - @compiler.environment.stubs(:known_resource_types).returns @known_resource_types - end - - it "should be able to find defined types" do - ref = @type.new(:type => "mydefine", :title => "/tmp/yay", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.should equal(@definition) - end - - it "should be able to find classes" do - ref = @type.new(:type => "class", :title => "myclass", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.should equal(@class) - end - - it "should be able to find nodes" do - ref = @type.new(:type => "node", :title => "mynode", :scope => @compiler.topscope) - ref.builtin?.should be_false - ref.definedtype.object_id.should == @nodedef.object_id - end - - it "should only look for fully qualified classes" do - top = newclass "top" - sub = newclass "other::top" - - scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :compiler => @compiler) - - ref = @type.new(:type => "class", :title => "top", :scope => scope) - ref.definedtype.name.should equal(top.name) - end - - it "should only look for fully qualified definitions" do - top = newdefine "top" - sub = newdefine "other::top" - - scope = @compiler.topscope.class.new(:parent => @compiler.topscope, :namespace => "other", :compiler => @compiler) - - ref = @type.new(:type => "top", :title => "foo", :scope => scope) - ref.definedtype.name.should equal(top.name) - end -end diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb index 799d05766..3d648fedf 100755 --- a/spec/unit/parser/scope.rb +++ b/spec/unit/parser/scope.rb @@ -8,6 +8,7 @@ describe Puppet::Parser::Scope do # This is necessary so we don't try to use the compiler to discover our parent. @topscope.parent = nil @scope = Puppet::Parser::Scope.new() + @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) @scope.parent = @topscope end @@ -104,7 +105,7 @@ describe Puppet::Parser::Scope do def create_class_scope(name) klass = newclass(name) - Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => @scope, :source => mock('source')).evaluate + Puppet::Parser::Resource.new("class", name, :scope => @scope, :source => mock('source')).evaluate return @scope.class_scope(klass) end @@ -315,6 +316,114 @@ describe Puppet::Parser::Scope do @scope.strinterp('==${10}==').should == "==value==" end + + describe "with qualified variables" do + before do + @scopes = {} + klass = @scope.known_resource_types.add(Puppet::Resource::Type.new(:hostclass, "")) + Puppet::Parser::Resource.new("class", :main, :scope => @scope, :source => mock('source')).evaluate + @scopes[""] = @scope.compiler.class_scope(klass) + @scopes[""].setvar("test", "value") + + %w{one one::two one::two::three}.each do |name| + klass = @scope.known_resource_types.add(Puppet::Resource::Type.new(:hostclass, name)) + Puppet::Parser::Resource.new("class", name, :scope => @scope, :source => mock('source')).evaluate + @scopes[name] = @scope.compiler.class_scope(klass) + @scopes[name].setvar("test", "value-#{name.sub(/.+::/,'')}") + end + end + { + "===${one::two::three::test}===" => "===value-three===", + "===$one::two::three::test===" => "===value-three===", + "===${one::two::test}===" => "===value-two===", + "===$one::two::test===" => "===value-two===", + "===${one::test}===" => "===value-one===", + "===$one::test===" => "===value-one===", + "===${::test}===" => "===value===", + "===$::test===" => "===value===" + }.each do |input, output| + it "should parse '#{input}' correctly" do + @scope.strinterp(input).should == output + end + end + end + + tests = { + "===${test}===" => "===value===", + "===${test} ${test} ${test}===" => "===value value value===", + "===$test ${test} $test===" => "===value value value===", + "===\\$test===" => "===$test===", + '===\\$test string===' => "===$test string===", + '===$test string===' => "===value string===", + '===a testing $===' => "===a testing $===", + '===a testing \$===' => "===a testing $===", + "===an escaped \\\n carriage return===" => "===an escaped carriage return===", + '\$' => "$", + '\s' => "\s", + '\t' => "\t", + '\n' => "\n" + } + + tests.each do |input, output| + it "should parse '#{input}' correctly" do + @scope.setvar("test", "value") + @scope.strinterp(input).should == output + end + end + + # #523 + %w{d f h l w z}.each do |l| + it "should parse '#{l}' when escaped" do + string = "\\" + l + @scope.strinterp(string).should == string + end + end + end + + def test_strinterp + # Make and evaluate our classes so the qualified lookups work + parser = mkparser + klass = parser.newclass("") + scope = mkscope(:parser => parser) + Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => scope, :source => mock('source')).evaluate + + assert_nothing_raised { + scope.setvar("test","value") + } + + scopes = {"" => scope} + + %w{one one::two one::two::three}.each do |name| + klass = parser.newclass(name) + Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => scope, :source => mock('source')).evaluate + scopes[name] = scope.compiler.class_scope(klass) + scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,'')) + end + + assert_equal("value", scope.lookupvar("::test"), "did not look up qualified value correctly") + tests.each do |input, output| + assert_nothing_raised("Failed to scan %s" % input.inspect) do + assert_equal(output, scope.strinterp(input), + 'did not parserret %s correctly' % input.inspect) + end + end + + logs = [] + Puppet::Util::Log.close + Puppet::Util::Log.newdestination(logs) + + # #523 + %w{d f h l w z}.each do |l| + string = "\\" + l + assert_nothing_raised do + assert_equal(string, scope.strinterp(string), + 'did not parserret %s correctly' % string) + end + + assert(logs.detect { |m| m.message =~ /Unrecognised escape/ }, + "Did not get warning about escape sequence with %s" % string) + logs.clear + end end describe "when setting ephemeral vars from matches" do @@ -357,4 +466,50 @@ describe Puppet::Parser::Scope do @scope.lookupvar("foo").should == "" end end + + it "should use its namespaces to find hostclasses" do + klass = @scope.known_resource_types.add Puppet::Resource::Type.new(:hostclass, "a::b::c") + @scope.add_namespace "a::b" + @scope.find_hostclass("c").should equal(klass) + end + + it "should use its namespaces to find definitions" do + define = @scope.known_resource_types.add Puppet::Resource::Type.new(:definition, "a::b::c") + @scope.add_namespace "a::b" + @scope.find_definition("c").should equal(define) + end + + describe "when managing defaults" do + it "should be able to set and lookup defaults" do + param = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param) + @scope.lookupdefaults(:mytype).should == {:myparam => param} + end + + it "should fail if a default is already defined and a new default is being defined" do + param = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param) + lambda { @scope.setdefaults(:mytype, param) }.should raise_error(Puppet::ParseError) + end + + it "should return multiple defaults at once" do + param1 = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param1) + param2 = Puppet::Parser::Resource::Param.new(:name => :other, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param2) + + @scope.lookupdefaults(:mytype).should == {:myparam => param1, :other => param2} + end + + it "should look up defaults defined in parent scopes" do + param1 = Puppet::Parser::Resource::Param.new(:name => :myparam, :value => "myvalue", :source => stub("source")) + @scope.setdefaults(:mytype, param1) + + child_scope = @scope.newscope + param2 = Puppet::Parser::Resource::Param.new(:name => :other, :value => "myvalue", :source => stub("source")) + child_scope.setdefaults(:mytype, param2) + + child_scope.lookupdefaults(:mytype).should == {:myparam => param1, :other => param2} + end + end end diff --git a/spec/unit/rails/param_value.rb b/spec/unit/rails/param_value.rb index 26e87fec2..070ac82ea 100755 --- a/spec/unit/rails/param_value.rb +++ b/spec/unit/rails/param_value.rb @@ -42,7 +42,7 @@ describe "Puppet::Rails::ParamValue" do end it "should not convert Resource References into strings" do - ref = Puppet::Resource::Reference.new(:file, "/file") + ref = Puppet::Resource.new(:file, "/file") Puppet::Rails::ParamValue.from_parser_param(:myparam, ref)[0][:value].should == ref end end diff --git a/spec/unit/resource.rb b/spec/unit/resource.rb index 73bbfd865..c97cd634f 100755 --- a/spec/unit/resource.rb +++ b/spec/unit/resource.rb @@ -12,71 +12,89 @@ describe Puppet::Resource do end end - describe "when initializing" do - it "should require the type and title" do - lambda { Puppet::Resource.new }.should raise_error(ArgumentError) - end + it "should have a :title attribute" do + Puppet::Resource.new(:file, "foo").title.should == "foo" + end - it "should create a resource reference with its type and title" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).with("file", "/f").returns ref - Puppet::Resource.new("file", "/f") - end + it "should require the type and title" do + lambda { Puppet::Resource.new }.should raise_error(ArgumentError) + end - it "should tag itself with its type" do - Puppet::Resource.new("file", "/f").should be_tagged("file") - end + it "should canonize types to capitalized strings" do + Puppet::Resource.new(:file, "foo").type.should == "File" + end - it "should tag itself with its title if the title is a valid tag" do - Puppet::Resource.new("file", "bar").should be_tagged("bar") - end + it "should canonize qualified types so all strings are capitalized" do + Puppet::Resource.new("foo::bar", "foo").type.should == "Foo::Bar" + end - it "should not tag itself with its title if the title is a not valid tag" do - Puppet::Resource.new("file", "/bar").should_not be_tagged("/bar") - end + it "should tag itself with its type" do + Puppet::Resource.new("file", "/f").should be_tagged("file") + end - it "should allow setting of attributes" do - Puppet::Resource.new("file", "/bar", :file => "/foo").file.should == "/foo" - Puppet::Resource.new("file", "/bar", :exported => true).should be_exported - end + it "should tag itself with its title if the title is a valid tag" do + Puppet::Resource.new("file", "bar").should be_tagged("bar") end - it "should use the resource reference to determine its type" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:type).returns "mytype" - resource.type.should == "mytype" + it "should not tag itself with its title if the title is a not valid tag" do + Puppet::Resource.new("file", "/bar").should_not be_tagged("/bar") end - it "should use its resource reference to determine its title" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:title).returns "mytitle" - resource.title.should == "mytitle" + it "should allow setting of attributes" do + Puppet::Resource.new("file", "/bar", :file => "/foo").file.should == "/foo" + Puppet::Resource.new("file", "/bar", :exported => true).should be_exported end - it "should use its resource reference to determine whether it is builtin" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:builtin_type?).returns "yep" - resource.builtin_type?.should == "yep" + it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do + ref = Puppet::Resource.new(:component, "foo") + ref.type.should == "Class" + ref.title.should == "foo" end - it "should call its builtin_type? method when 'builtin?' is called" do - resource = Puppet::Resource.new("file", "/f") - resource.expects(:builtin_type?).returns "foo" - resource.builtin?.should == "foo" + it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do + ref = Puppet::Resource.new(:component, "foo::bar[yay]") + ref.type.should == "Foo::Bar" + ref.title.should == "yay" end - it "should use its resource reference to produce its canonical reference string" do - ref = Puppet::Resource::Reference.new("file", "/f") - Puppet::Resource::Reference.expects(:new).returns ref - resource = Puppet::Resource.new("file", "/f") - ref.expects(:to_s).returns "Foo[bar]" - resource.ref.should == "Foo[bar]" + it "should set the type to 'Class' if it is nil and the title contains no square brackets" do + ref = Puppet::Resource.new(nil, "yay") + ref.type.should == "Class" + ref.title.should == "yay" + end + + it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do + ref = Puppet::Resource.new(nil, "foo::bar[yay]") + ref.type.should == "Foo::Bar" + ref.title.should == "yay" + end + + it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains nested square brackets" do + ref = Puppet::Resource.new(nil, "foo::bar[baz[yay]]") + ref.type.should == "Foo::Bar" + ref.title.should =="baz[yay]" + end + + it "should interpret the type as a reference and assign appropriately if the title is nil and the type contains square brackets" do + ref = Puppet::Resource.new("foo::bar[baz]") + ref.type.should == "Foo::Bar" + ref.title.should =="baz" + end + + it "should be able to extract its information from a Puppet::Type instance" do + ral = Puppet::Type.type(:file).new :path => "/foo" + ref = Puppet::Resource.new(ral) + ref.type.should == "File" + ref.title.should == "/foo" + end + + + it "should fail if the title is nil and the type is not a valid resource reference string" do + lambda { Puppet::Resource.new("foo") }.should raise_error(ArgumentError) + end + + it "should be able to produce a backward-compatible reference array" do + Puppet::Resource.new("foobar", "/f").to_trans_ref.should == %w{Foobar /f} end it "should be taggable" do @@ -94,12 +112,16 @@ describe Puppet::Resource do Puppet::Resource.new("file", "/my/file", :environment => :foo).environment.name.should == :foo end - it "should support a namespace attribute" do - Puppet::Resource.new("file", "/my/file", :namespace => :foo).namespace.should == :foo + it "should support specifying namespaces" do + Puppet::Resource.new("file", "/my/file", :namespaces => [:foo]).namespaces.should == [:foo] + end + + it "should convert namespaces to an array if not specified as one" do + Puppet::Resource.new("file", "/my/file", :namespaces => :foo).namespaces.should == [:foo] end - it "should default to a namespace of an empty string" do - Puppet::Resource.new("file", "/my/file").namespace.should == "" + it "should default to a single amespace of an empty string" do + Puppet::Resource.new("file", "/my/file").namespaces.should == [""] end it "should be able to look up its resource type when the type is a builtin resource" do @@ -130,16 +152,16 @@ describe Puppet::Resource do resource.resource_type.should equal(klass) end - it "should use its namespace when looking up defined resource types" do - resource = Puppet::Resource.new("bar", "/my/file", :namespace => "foo") + it "should use its namespaces when looking up defined resource types" do + resource = Puppet::Resource.new("bar", "/my/file", :namespaces => ["foo"]) type = Puppet::Resource::Type.new(:definition, "foo::bar") resource.environment.known_resource_types.add type resource.resource_type.should equal(type) end - it "should use its namespace when looking up host classes" do - resource = Puppet::Resource.new("class", "bar", :namespace => "foo") + it "should use its namespaces when looking up host classes" do + resource = Puppet::Resource.new("class", "bar", :namespaces => ["foo"]) type = Puppet::Resource::Type.new(:hostclass, "foo::bar") resource.environment.known_resource_types.add type @@ -171,6 +193,30 @@ describe Puppet::Resource do resource[:yay] = true end + it "should be considered equivalent to another resource if their type and title match and no parameters are set" do + Puppet::Resource.new("file", "/f").should == Puppet::Resource.new("file", "/f") + end + + it "should be considered equivalent to another resource if their type, title, and parameters are equal" do + Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}).should == Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}) + end + + it "should not be considered equivalent to another resource if their type and title match but parameters are different" do + Puppet::Resource.new("file", "/f", :parameters => {:fee => "baz"}).should_not == Puppet::Resource.new("file", "/f", :parameters => {:foo => "bar"}) + end + + it "should not be considered equivalent to a non-resource" do + Puppet::Resource.new("file", "/f").should_not == "foo" + end + + it "should not be considered equivalent to another resource if their types do not match" do + Puppet::Resource.new("file", "/f").should_not == Puppet::Resource.new("exec", "/f") + end + + it "should not be considered equivalent to another resource if their titles do not match" do + Puppet::Resource.new("file", "/foo").should_not == Puppet::Resource.new("file", "/f") + end + describe "when managing parameters" do before do @resource = Puppet::Resource.new("file", "/my/file") @@ -305,7 +351,10 @@ describe Puppet::Resource do end it "should set :name to the title if :name is not present for non-builtin types" do + krt = Puppet::Resource::TypeCollection.new("myenv") + krt.add Puppet::Resource::Type.new(:definition, :foo) resource = Puppet::Resource.new :foo, "bar" + resource.stubs(:known_resource_types).returns krt resource.to_hash[:name].should == "bar" end end @@ -334,25 +383,19 @@ describe Puppet::Resource do end describe "when converting to a RAL resource" do - before do - @resource = Puppet::Resource.new("file", "/my/file") - @resource["one"] = "test" - @resource["two"] = "other" - end - - it "should use the resource type's :create method to create the resource if the resource is of a builtin type" do - type = mock 'resource type' - type.expects(:new).with(@resource).returns(:myresource) - Puppet::Type.expects(:type).with(@resource.type).returns(type) - @resource.to_ral.should == :myresource + it "should use the resource type's :new method to create the resource if the resource is of a builtin type" do + resource = Puppet::Resource.new("file", "/my/file") + result = resource.to_ral + result.should be_instance_of(Puppet::Type.type(:file)) + result[:path].should == "/my/file" end it "should convert to a component instance if the resource type is not of a builtin type" do - component = mock 'component type' - Puppet::Type::Component.expects(:new).with(@resource).returns "meh" + resource = Puppet::Resource.new("foobar", "somename") + result = resource.to_ral - Puppet::Type.expects(:type).with(@resource.type).returns(nil) - @resource.to_ral.should == "meh" + result.should be_instance_of(Puppet::Type.type(:component)) + result.title.should == "Foobar[somename]" end end @@ -450,13 +493,13 @@ describe Puppet::Resource do end it "should convert resource references into the backward-compatible form" do - @resource[:foo] = Puppet::Resource::Reference.new(:file, "/f") - @resource.to_trans["foo"].should == %w{file /f} + @resource[:foo] = Puppet::Resource.new(:file, "/f") + @resource.to_trans["foo"].should == %w{File /f} end it "should convert resource references into the backward-compatible form even when within arrays" do - @resource[:foo] = ["a", Puppet::Resource::Reference.new(:file, "/f")] - @resource.to_trans["foo"].should == ["a", %w{file /f}] + @resource[:foo] = ["a", Puppet::Resource.new(:file, "/f")] + @resource.to_trans["foo"].should == ["a", %w{File /f}] end end end @@ -618,4 +661,16 @@ describe Puppet::Resource do Puppet::Resource.new("file", "/my/file").name.should == "File//my/file" end end + + describe "when resolving resources with a catalog" do + it "should resolve all resources using the catalog" do + catalog = mock 'catalog' + resource = Puppet::Resource.new("foo::bar", "yay") + resource.catalog = catalog + + catalog.expects(:resource).with("Foo::Bar[yay]").returns(:myresource) + + resource.resolve.should == :myresource + end + end end diff --git a/spec/unit/resource/catalog.rb b/spec/unit/resource/catalog.rb index e2fe72489..6c6af24ce 100755 --- a/spec/unit/resource/catalog.rb +++ b/spec/unit/resource/catalog.rb @@ -109,7 +109,7 @@ describe Puppet::Resource::Catalog, "when compiling" do end def mkresource(type, name) - Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope) + Puppet::Parser::Resource.new(type, name, :source => @source, :scope => @scope) end it "should always create a TransBucket for the 'main' class" do diff --git a/spec/unit/resource/reference.rb b/spec/unit/resource/reference.rb deleted file mode 100755 index 7a9704508..000000000 --- a/spec/unit/resource/reference.rb +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../spec_helper' - -require 'puppet/resource/reference' - -describe Puppet::Resource::Reference do - it "should have a :title attribute" do - Puppet::Resource::Reference.new(:file, "foo").title.should == "foo" - end - - it "should canonize types to capitalized strings" do - Puppet::Resource::Reference.new(:file, "foo").type.should == "File" - end - - it "should canonize qualified types so all strings are capitalized" do - Puppet::Resource::Reference.new("foo::bar", "foo").type.should == "Foo::Bar" - end - - it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do - ref = Puppet::Resource::Reference.new(:component, "foo") - ref.type.should == "Class" - ref.title.should == "foo" - end - - it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do - ref = Puppet::Resource::Reference.new(:component, "foo::bar[yay]") - ref.type.should == "Foo::Bar" - ref.title.should == "yay" - end - - it "should set the type to 'Class' if it is nil and the title contains no square brackets" do - ref = Puppet::Resource::Reference.new(nil, "yay") - ref.type.should == "Class" - ref.title.should == "yay" - end - - it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do - ref = Puppet::Resource::Reference.new(nil, "foo::bar[yay]") - ref.type.should == "Foo::Bar" - ref.title.should == "yay" - end - - it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains nested square brackets" do - ref = Puppet::Resource::Reference.new(nil, "foo::bar[baz[yay]]") - ref.type.should == "Foo::Bar" - ref.title.should =="baz[yay]" - end - - it "should interpret the type as a reference and assign appropriately if the title is nil and the type contains square brackets" do - ref = Puppet::Resource::Reference.new("foo::bar[baz]") - ref.type.should == "Foo::Bar" - ref.title.should =="baz" - end - - it "should be able to extract its information from a Puppet::Type instance" do - ral = Puppet::Type.type(:file).new :path => "/foo" - ref = Puppet::Resource::Reference.new(ral) - ref.type.should == "File" - ref.title.should == "/foo" - end - - - it "should fail if the title is nil and the type is not a valid resource reference string" do - lambda { Puppet::Resource::Reference.new("foo") }.should raise_error(ArgumentError) - end - - it "should be considered builtin if an existing resource type matches the type" do - Puppet::Resource::Reference.new("file", "/f").should be_builtin_type - end - - it "should be not considered builtin if an existing resource type does not match the type" do - Puppet::Resource::Reference.new("foobar", "/f").should_not be_builtin_type - end - - it "should be able to produce a backward-compatible reference array" do - Puppet::Resource::Reference.new("foobar", "/f").to_trans_ref.should == %w{Foobar /f} - end - - it "should downcase resource types when producing a backward-compatible reference array for builtin resource types" do - Puppet::Resource::Reference.new("file", "/f").to_trans_ref.should == %w{file /f} - end - - it "should be considered equivalent to another reference if their type and title match" do - Puppet::Resource::Reference.new("file", "/f").should == Puppet::Resource::Reference.new("file", "/f") - end - - it "should not be considered equivalent to a non-reference" do - Puppet::Resource::Reference.new("file", "/f").should_not == "foo" - end - - it "should not be considered equivalent to another reference if their types do not match" do - Puppet::Resource::Reference.new("file", "/f").should_not == Puppet::Resource::Reference.new("exec", "/f") - end - - it "should not be considered equivalent to another reference if their titles do not match" do - Puppet::Resource::Reference.new("file", "/foo").should_not == Puppet::Resource::Reference.new("file", "/f") - end - - describe "when resolving resources with a catalog" do - it "should resolve all resources using the catalog" do - config = mock 'catalog' - ref = Puppet::Resource::Reference.new("foo::bar", "yay") - ref.catalog = config - - config.expects(:resource).with("Foo::Bar[yay]").returns(:myresource) - - ref.resolve.should == :myresource - end - end -end diff --git a/spec/unit/resource/type.rb b/spec/unit/resource/type.rb index 0a2f447ef..1a19cf4f0 100755 --- a/spec/unit/resource/type.rb +++ b/spec/unit/resource/type.rb @@ -456,13 +456,13 @@ describe Puppet::Resource::Type do end it "should fail unless it is a class" do - lambda { Puppet::Resource::Type.new(:node, "bar").merge("foo") }.should raise_error(ArgumentError) + lambda { Puppet::Resource::Type.new(:node, "bar").merge("foo") }.should raise_error(Puppet::Error) end it "should fail unless the source instance is a class" do dest = Puppet::Resource::Type.new(:hostclass, "bar") source = Puppet::Resource::Type.new(:node, "foo") - lambda { dest.merge(source) }.should raise_error(ArgumentError) + lambda { dest.merge(source) }.should raise_error(Puppet::Error) end it "should fail if both classes have different parent classes" do @@ -471,7 +471,7 @@ describe Puppet::Resource::Type do code.add Puppet::Resource::Type.new(:hostclass, parent) code.add Puppet::Resource::Type.new(:hostclass, child, :parent => parent) end - lambda { code.hostclass("b").merge(code.hostclass("d")) }.should raise_error(ArgumentError) + lambda { code.hostclass("b").merge(code.hostclass("d")) }.should raise_error(Puppet::Error) end it "should copy the other class's parent if it has not parent" do diff --git a/spec/unit/resource/type_collection.rb b/spec/unit/resource/type_collection.rb index 3de5e504b..a2a213f5a 100644 --- a/spec/unit/resource/type_collection.rb +++ b/spec/unit/resource/type_collection.rb @@ -64,7 +64,32 @@ describe Puppet::Resource::TypeCollection do @code.definition("foo").should equal(define) end + it "should merge new classes with existing classes of the same name" do + loader = Puppet::Resource::TypeCollection.new("env") + first = Puppet::Resource::Type.new(:hostclass, "foo") + second = Puppet::Resource::Type.new(:hostclass, "foo") + loader.add first + first.expects(:merge).with(second) + loader.add(second) + end + + it "should remove all nodes, classes, and definitions when cleared" do + loader = Puppet::Resource::TypeCollection.new("env") + loader.add Puppet::Resource::Type.new(:hostclass, "class") + loader.add Puppet::Resource::Type.new(:definition, "define") + loader.add Puppet::Resource::Type.new(:node, "node") + + loader.clear + loader.hostclass("class").should be_nil + loader.definition("define").should be_nil + loader.node("node").should be_nil + end + %w{hostclass node definition}.each do |data| + before do + @instance = Puppet::Resource::Type.new(data, "foo") + end + it "should have a method for adding a #{data}" do Puppet::Resource::TypeCollection.new("env").should respond_to("add_" + data) end @@ -75,10 +100,12 @@ describe Puppet::Resource::TypeCollection do loader.send(data, @instance.name).should equal(@instance) end - it "should fail to add a #{data} when one already exists" do - loader = Puppet::Resource::TypeCollection.new("env") - loader.add @instance - lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError) + unless data == "hostclass" + it "should fail to add a #{data} when one already exists" do + loader = Puppet::Resource::TypeCollection.new("env") + loader.add @instance + lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError) + end end it "should return the added #{data}" do @@ -127,6 +154,13 @@ describe Puppet::Resource::TypeCollection do loader.find("namespace", "::foo::bar", :hostclass).should be_nil end + it "should be able to find classes in the base namespace" do + loader = Puppet::Resource::TypeCollection.new("env") + instance = Puppet::Resource::Type.new(:hostclass, "foo") + loader.add instance + loader.find("", "foo", :hostclass).should equal(instance) + end + it "should return the partially qualified object if it exists in a provided namespace" do loader = Puppet::Resource::TypeCollection.new("env") instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz") diff --git a/spec/unit/transportable.rb b/spec/unit/transportable.rb new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/spec/unit/transportable.rb diff --git a/spec/unit/type.rb b/spec/unit/type.rb index 73f249faa..b2f4bcbd4 100755 --- a/spec/unit/type.rb +++ b/spec/unit/type.rb @@ -464,13 +464,13 @@ describe Puppet::Type::RelationshipMetaparam do @metaparam = Puppet::Type.metaparamclass(:require).new :resource => @resource end - it "should accept Puppet::Resource::Reference instances" do - ref = Puppet::Resource::Reference.new(:file, "/foo") + it "should accept Puppet::Resource instances" do + ref = Puppet::Resource.new(:file, "/foo") @metaparam.munge(ref)[0].should equal(ref) end - it "should turn any string into a Puppet::Resource::Reference" do - @metaparam.munge("File[/ref]")[0].should be_instance_of(Puppet::Resource::Reference) + it "should turn any string into a Puppet::Resource" do + @metaparam.munge("File[/ref]")[0].should be_instance_of(Puppet::Resource) end end diff --git a/spec/unit/type/tidy.rb b/spec/unit/type/tidy.rb index ccec9ed7c..9bee7d700 100755 --- a/spec/unit/type/tidy.rb +++ b/spec/unit/type/tidy.rb @@ -390,7 +390,7 @@ describe tidy do "/what/ever/one/subone" => ["/what/ever/one/subone/ssone"] }.each do |parent, children| children.each do |child| - ref = Puppet::Resource::Reference.new(:file, child) + ref = Puppet::Resource.new(:file, child) result[parent][:require].find { |req| req.to_s == ref.to_s }.should_not be_nil end end diff --git a/test/language/functions.rb b/test/language/functions.rb index af0732559..70605f8f6 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -289,16 +289,12 @@ class TestLangFunctions < Test::Unit::TestCase Puppet[:code] = %{file { "#{file}": content => template("#{template}") }} Puppet[:environment] = "yay" - interp = Puppet::Parser::Interpreter.new node = mknode - node.stubs(:environment).returns("yay") + node.stubs(:environment).returns Puppet::Node::Environment.new Puppet[:environment] = "yay" - catalog = nil - assert_nothing_raised { - catalog = interp.compile(node) - } + catalog = Puppet::Parser::Compiler.new(node).compile version = catalog.version @@ -317,7 +313,7 @@ class TestLangFunctions < Test::Unit::TestCase f.puts "new text" end - newversion = interp.compile(node).version + newversion = Puppet::Parser::Compiler.new(node).compile.version assert(version != newversion, "Parse date did not change") end @@ -385,100 +381,6 @@ class TestLangFunctions < Test::Unit::TestCase "Did not set function correctly") end - def test_realize - scope = mkscope - parser = scope.compiler.parser - - realize = Puppet::Parser::Functions.function(:realize) - - # Make a definition - parser.newdefine("mytype") - - [%w{file /tmp/virtual}, %w{mytype yay}].each do |type, title| - # Make a virtual resource - virtual = mkresource(:type => type, :title => title, - :virtual => true, :params => {}, :scope => scope) - - scope.compiler.add_resource(scope, virtual) - - ref = Puppet::Parser::Resource::Reference.new( - :type => type, :title => title, - :scope => scope - ) - # Now call the realize function - assert_nothing_raised do - scope.function_realize(ref) - end - - # Make sure it created a collection - assert_equal(1, scope.compiler.collections.length, - "Did not set collection") - - assert_nothing_raised do - scope.compiler.collections.each do |coll| coll.evaluate end - end - scope.compiler.collections.clear - - # Now make sure the virtual resource is no longer virtual - assert(! virtual.virtual?, "Did not make virtual resource real") - end - - # Make sure we puke on any resource that doesn't exist - none = Puppet::Parser::Resource::Reference.new( - :type => "file", :title => "/tmp/nosuchfile", - :scope => scope - ) - - # The function works - assert_nothing_raised do - scope.function_realize(none.to_s) - end - - # Make sure it created a collection - assert_equal(1, scope.compiler.collections.length, - "Did not set collection") - - # And the collection has our resource in it - assert_equal([none.to_s], scope.compiler.collections[0].resources, - "Did not set resources in collection") - end - - def test_defined - scope = mkscope - parser = scope.compiler.parser - - defined = Puppet::Parser::Functions.function(:defined) - - parser.newclass("yayness") - parser.newdefine("rahness") - - assert_nothing_raised do - assert(scope.function_defined("yayness"), "yayness class was not considered defined") - assert(scope.function_defined("rahness"), "rahness definition was not considered defined") - assert(scope.function_defined("service"), "service type was not considered defined") - assert(! scope.function_defined("fakness"), "fakeness was considered defined") - end - - # Now make sure any match in a list will work - assert(scope.function_defined(["booness", "yayness", "fakeness"]), - "A single answer was not sufficient to return true") - - # and make sure multiple falses are still false - assert(! scope.function_defined(%w{no otherno stillno}), - "Multiple falses were somehow true") - - # Now make sure we can test resources - scope.compiler.add_resource(scope, mkresource(:type => "file", :title => "/tmp/rahness", - :scope => scope, :source => scope.source, - :params => {:owner => "root"})) - - yep = Puppet::Parser::Resource::Reference.new(:type => "file", :title => "/tmp/rahness") - nope = Puppet::Parser::Resource::Reference.new(:type => "file", :title => "/tmp/fooness") - - assert(scope.function_defined([yep]), "valid resource was not considered defined") - assert(! scope.function_defined([nope]), "invalid resource was considered defined") - end - def test_search parser = mkparser scope = mkscope(:parser => parser) @@ -503,7 +405,7 @@ class TestLangFunctions < Test::Unit::TestCase def test_include scope = mkscope - parser = scope.compiler.parser + parser = mkparser include = Puppet::Parser::Functions.function(:include) @@ -569,7 +471,7 @@ class TestLangFunctions < Test::Unit::TestCase generate = Puppet::Parser::Functions.function(:generate) scope = mkscope - parser = scope.compiler.parser + parser = mkparser val = nil assert_nothing_raised("Could not call generator with no args") do diff --git a/test/language/parser.rb b/test/language/parser.rb index a3311f423..b721490c3 100755 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -18,8 +18,14 @@ class TestParser < Test::Unit::TestCase #@lexer = Puppet::Parser::Lexer.new() end + def teardown + super + Puppet::Node::Environment.clear + end + def test_each_file textfiles { |file| + Puppet::Node::Environment.clear parser = mkparser Puppet.debug("parsing %s" % file) if __FILE__ == $0 assert_nothing_raised() { @@ -379,9 +385,7 @@ file { "/tmp/yayness": assert_instance_of(Puppet::Parser::AST::IfStatement, ret) parser = mkparser str2 = %{if true { #{exec.call("true")} } else { #{exec.call("false")} }} - assert_nothing_raised { - ret = parser.parse(str2).hostclass("").code[0] - } + ret = parser.parse(str2).hostclass("").code[0] assert_instance_of(Puppet::Parser::AST::IfStatement, ret) assert_instance_of(Puppet::Parser::AST::Else, ret.else) end @@ -410,7 +414,7 @@ file { "/tmp/yayness": } sub = parser.hostclass("container::one") assert(sub, "Could not find one") - assert_equal("container::deep::sub", sub.parentclass) + assert_equal("container::deep::sub", sub.parent) # Finally, try including a qualified class assert_nothing_raised("Could not include fully qualified class") { @@ -435,7 +439,7 @@ file { "/tmp/yayness": assert_nothing_raised do out = parser.parse "Exec { path => '/usr/bin:/usr/sbin' }" assert_instance_of(Puppet::Resource::TypeCollection, out) - assert_equal("", parser.hostclass("").classname) + assert_equal("", parser.hostclass("").name) assert_equal("", parser.hostclass("").namespace) end end @@ -520,6 +524,7 @@ file { "/tmp/yayness": end tests.each do |form| + Puppet::Node::Environment.clear parser = mkparser if form == :virtual @@ -549,6 +554,7 @@ file { "/tmp/yayness": def test_collectionexpressions %w{== !=}.each do |oper| + Puppet::Node::Environment.clear str = "File <| title #{oper} '/tmp/testing' |>" parser = mkparser @@ -616,30 +622,6 @@ file { "/tmp/yayness": end end - # We've had problems with files other than site.pp importing into main. - def test_importing_into_main - top = tempfile() - other = tempfile() - File.open(top, "w") do |f| - f.puts "import '#{other}'" - end - - file = tempfile() - File.open(other, "w") do |f| - f.puts "file { '#{file}': ensure => present }" - end - - Puppet[:manifest] = top - interp = Puppet::Parser::Interpreter.new - - code = nil - assert_nothing_raised do - code = interp.compile(mknode).extract.flatten - end - assert(code.length == 1, "Did not get the file") - assert_instance_of(Puppet::TransObject, code[0]) - end - def test_fully_qualified_definitions parser = mkparser @@ -803,196 +785,10 @@ file { "/tmp/yayness": end assert_instance_of(Puppet::Resource::TypeCollection, result, "Did not get a ASTSet back from parsing") - assert_instance_of(AST::HostClass, result.hostclass("yay"), "Did not create 'yay' class") - assert_instance_of(AST::HostClass, result.hostclass(""), "Did not create main class") - assert_instance_of(AST::Definition, result.definition("bar"), "Did not create 'bar' definition") - assert_instance_of(AST::Node, result.node("foo"), "Did not create 'foo' node") - end - - # Make sure our node gets added to the node table. - def test_newnode - parser = mkparser - - # First just try calling it directly - assert_nothing_raised { - parser.newnode("mynode", :code => :yay) - } - - assert_equal(:yay, parser.node("mynode").code) - - # Now make sure that trying to redefine it throws an error. - assert_raise(Puppet::ParseError) { - parser.newnode("mynode", {}) - } - - # Now try one with no code - assert_nothing_raised { - parser.newnode("simplenode", :parent => :foo) - } - - # Now define the parent node - parser.newnode(:foo) - - # And make sure we get things back correctly - assert_equal(:foo, parser.node("simplenode").parentclass) - assert_nil(parser.node("simplenode").code) - - # Now make sure that trying to redefine it throws an error. - assert_raise(Puppet::ParseError) { - parser.newnode("mynode", {}) - } - - # Test multiple names - names = ["one", "two", "three"] - assert_nothing_raised { - parser.newnode(names, {:code => :yay, :parent => :foo}) - } - - names.each do |name| - assert_equal(:yay, parser.node(name).code) - assert_equal(:foo, parser.node(name).parentclass) - # Now make sure that trying to redefine it throws an error. - assert_raise(Puppet::ParseError) { - parser.newnode(name, {}) - } - end - end - - def test_newdefine - parser = mkparser - - assert_nothing_raised { - parser.newdefine("mydefine", :code => :yay, - :arguments => ["a", stringobj("b")]) - } - - mydefine = parser.definition("mydefine") - assert(mydefine, "Could not find definition") - assert_equal("", mydefine.namespace) - assert_equal("mydefine", mydefine.classname) - - assert_raise(Puppet::ParseError) do - parser.newdefine("mydefine", :code => :yay, - :arguments => ["a", stringobj("b")]) - end - - # Now define the same thing in a different scope - assert_nothing_raised { - parser.newdefine("other::mydefine", :code => :other, - :arguments => ["a", stringobj("b")]) - } - other = parser.definition("other::mydefine") - assert(other, "Could not find definition") - assert(parser.definition("other::mydefine"), - "Could not find other::mydefine") - assert_equal(:other, other.code) - assert_equal("other", other.namespace) - assert_equal("other::mydefine", other.classname) - end - - def test_newclass - scope = mkscope - parser = scope.compiler.parser - - mkcode = proc do |ary| - classes = ary.collect do |string| - AST::FlatString.new(:value => string) - end - AST::ASTArray.new(:children => classes) - end - - - # First make sure that code is being appended - code = mkcode.call(%w{original code}) - - klass = nil - assert_nothing_raised { - klass = parser.newclass("myclass", :code => code) - } - - assert(klass, "Did not return class") - - assert(parser.hostclass("myclass"), "Could not find definition") - assert_equal("myclass", parser.hostclass("myclass").classname) - assert_equal(%w{original code}, - parser.hostclass("myclass").code.evaluate(scope)) - - # Newclass behaves differently than the others -- it just appends - # the code to the existing class. - code = mkcode.call(%w{something new}) - assert_nothing_raised do - klass = parser.newclass("myclass", :code => code) - end - assert(klass, "Did not return class when appending") - assert_equal(%w{original code something new}, - parser.hostclass("myclass").code.evaluate(scope)) - - # Now create the same class name in a different scope - assert_nothing_raised { - klass = parser.newclass("other::myclass", - :code => mkcode.call(%w{something diff})) - } - assert(klass, "Did not return class") - other = parser.hostclass("other::myclass") - assert(other, "Could not find class") - assert_equal("other::myclass", other.classname) - assert_equal("other::myclass", other.namespace) - assert_equal(%w{something diff}, - other.code.evaluate(scope)) - - # Make sure newclass deals correctly with nodes with no code - klass = parser.newclass("nocode") - assert(klass, "Did not return class") - - assert_nothing_raised do - klass = parser.newclass("nocode", :code => mkcode.call(%w{yay test})) - end - assert(klass, "Did not return class with no code") - assert_equal(%w{yay test}, - parser.hostclass("nocode").code.evaluate(scope)) - - # Then try merging something into nothing - parser.newclass("nocode2", :code => mkcode.call(%w{foo test})) - assert(klass, "Did not return class with no code") - - assert_nothing_raised do - klass = parser.newclass("nocode2") - end - assert(klass, "Did not return class with no code") - assert_equal(%w{foo test}, - parser.hostclass("nocode2").code.evaluate(scope)) - - # And lastly, nothing and nothing - klass = parser.newclass("nocode3") - assert(klass, "Did not return class with no code") - - assert_nothing_raised do - klass = parser.newclass("nocode3") - end - assert(klass, "Did not return class with no code") - assert_nil(parser.hostclass("nocode3").code) - end - - # Make sure you can't have classes and defines with the same name in the - # same scope. - def test_classes_beat_defines - parser = mkparser - - assert_nothing_raised { - parser.newclass("yay::funtest") - } - - assert_raise(Puppet::ParseError) do - parser.newdefine("yay::funtest") - end - - assert_nothing_raised { - parser.newdefine("yay::yaytest") - } - - assert_raise(Puppet::ParseError) do - parser.newclass("yay::yaytest") - end + assert_instance_of(Puppet::Resource::Type, result.hostclass("yay"), "Did not create 'yay' class") + assert_instance_of(Puppet::Resource::Type, result.hostclass(""), "Did not create main class") + assert_instance_of(Puppet::Resource::Type, result.definition("bar"), "Did not create 'bar' definition") + assert_instance_of(Puppet::Resource::Type, result.node("foo"), "Did not create 'foo' node") end def test_namesplit @@ -1009,50 +805,6 @@ file { "/tmp/yayness": end end - # Now make sure we get appropriate behaviour with parent class conflicts. - def test_newclass_parentage - parser = mkparser - parser.newclass("base1") - parser.newclass("one::two::three") - - # First create it with no parentclass. - assert_nothing_raised { - parser.newclass("sub") - } - assert(parser.hostclass("sub"), "Could not find definition") - assert_nil(parser.hostclass("sub").parentclass) - - # Make sure we can't set the parent class to ourself. - assert_raise(Puppet::ParseError) { - parser.newclass("sub", :parent => "sub") - } - - # Now create another one, with a parentclass. - assert_nothing_raised { - parser.newclass("sub", :parent => "base1") - } - - # Make sure we get the right parent class, and make sure it's not an object. - assert_equal("base1", - parser.hostclass("sub").parentclass) - - # Now make sure we get a failure if we try to conflict. - assert_raise(Puppet::ParseError) { - parser.newclass("sub", :parent => "one::two::three") - } - - # Make sure that failure didn't screw us up in any way. - assert_equal("base1", - parser.hostclass("sub").parentclass) - # But make sure we can create a class with a fq parent - assert_nothing_raised { - parser.newclass("another", :parent => "one::two::three") - } - assert_equal("one::two::three", - parser.hostclass("another").parentclass) - - end - # Setup a module. def mk_module(name, files = {}) mdir = File.join(@dir, name) @@ -1095,22 +847,22 @@ file { "/tmp/yayness": # Try to load the module automatically now klass = parser.find_hostclass("", name) - assert_instance_of(AST::HostClass, klass, "Did not autoload class from module init file") - assert_equal(name, klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload class from module init file") + assert_equal(name, klass.name, "Incorrect class was returned") # Try loading the simple module when we're in something other than the base namespace. parser = mkparser klass = parser.find_hostclass("something::else", name) - assert_instance_of(AST::HostClass, klass, "Did not autoload class from module init file") - assert_equal(name, klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload class from module init file") + assert_equal(name, klass.name, "Incorrect class was returned") # Now try it with a definition as the base file name = "simpdef" mk_module(name, :define => true, :init => [name]) klass = parser.find_definition("", name) - assert_instance_of(AST::Definition, klass, "Did not autoload class from module init file") - assert_equal(name, klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload class from module init file") + assert_equal(name, klass.name, "Incorrect class was returned") # Now try it with namespace classes where both classes are in the init file parser = mkparser @@ -1120,14 +872,14 @@ file { "/tmp/yayness": # First try it with a namespace klass = parser.find_hostclass("both", name) - assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from module init file with a namespace") - assert_equal("both::sub", klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from module init file with a namespace") + assert_equal("both::sub", klass.name, "Incorrect class was returned") # Now try it using the fully qualified name parser = mkparser klass = parser.find_hostclass("", "both::sub") - assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from module init file with no namespace") - assert_equal("both::sub", klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from module init file with no namespace") + assert_equal("both::sub", klass.name, "Incorrect class was returned") # Now try it with the class in a different file @@ -1138,14 +890,14 @@ file { "/tmp/yayness": # First try it with a namespace klass = parser.find_hostclass("separate", name) - assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from separate file with a namespace") - assert_equal("separate::sub", klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from separate file with a namespace") + assert_equal("separate::sub", klass.name, "Incorrect class was returned") # Now try it using the fully qualified name parser = mkparser klass = parser.find_hostclass("", "separate::sub") - assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from separate file with no namespace") - assert_equal("separate::sub", klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from separate file with no namespace") + assert_equal("separate::sub", klass.name, "Incorrect class was returned") # Now make sure we don't get a failure when there's no module file parser = mkparser @@ -1157,22 +909,22 @@ file { "/tmp/yayness": assert_nothing_raised("Could not autoload file when module file is missing") do klass = parser.find_hostclass("alone", name) end - assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from alone file with a namespace") - assert_equal("alone::sub", klass.classname, "Incorrect class was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from alone file with a namespace") + assert_equal("alone::sub", klass.name, "Incorrect class was returned") # Now try it using the fully qualified name parser = mkparser klass = parser.find_hostclass("", "alone::sub") - 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") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload sub class from alone file with no namespace") + assert_equal("alone::sub", klass.name, "Incorrect class was returned") # and with the definition in its own file name = "mymod" mk_module(name, :define => true, :mydefine => ["mymod::mydefine"]) klass = parser.find_definition("", "mymod::mydefine") - assert_instance_of(AST::Definition, klass, "Did not autoload definition from its own file") - assert_equal("mymod::mydefine", klass.classname, "Incorrect definition was returned") + assert_instance_of(Puppet::Resource::Type, klass, "Did not autoload definition from its own file") + assert_equal("mymod::mydefine", klass.name, "Incorrect definition was returned") end # Make sure class, node, and define methods are case-insensitive @@ -1191,25 +943,4 @@ file { "/tmp/yayness": assert_equal(result, parser.find_definition("", "fUntEst"), "%s was not matched" % "fUntEst") end - - def test_manifests_with_multiple_environments - parser = mkparser :environment => "something" - - # We use an exception to cut short the processing to simplify our stubbing - #Puppet::Module.expects(:find_manifests).with("test", {:cwd => ".", :environment => "something"}).raises(Puppet::ParseError) - Puppet::Parser::Files.expects(:find_manifests).with("test", {:cwd => ".", :environment => "something"}).returns([]) - - assert_raise(Puppet::ImportError) do - parser.import("test") - end - end - - def test_watch_file_only_once - FileTest.stubs(:exists?).returns(true) - parser = mkparser - parser.watch_file("doh") - parser.watch_file("doh") - assert_equal(1, parser.files.select { |name, file| file.file == "doh" }.length, "Length of watched 'doh' files was not 1") - end end - diff --git a/test/language/resource.rb b/test/language/resource.rb deleted file mode 100755 index c1d116f9e..000000000 --- a/test/language/resource.rb +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppettest' -require 'puppettest/resourcetesting' - -class TestResource < PuppetTest::TestCase - include PuppetTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - Parser = Puppet::Parser - AST = Parser::AST - Resource = Puppet::Parser::Resource - Reference = Puppet::Parser::Resource::Reference - - def setup - super - Puppet[:trace] = false - end - - def teardown - mocha_verify - end - - # 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 - - def test_set_parameter - res = mkresource - params = res.instance_variable_get("@params") - - # First test the simple case: It's already a parameter - param = stub('param', :name => "pname") - param.expects(:is_a?).with(Resource::Param).returns(true) - 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 - # There are three cases here: - - # 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(:valid_parameter?).with("good").returns(true) - assert(res.send(:paramcheck, :good), "Did not allow valid param") - - # It's name or title - klass.expects(:valid_parameter?).with("name").returns(false) - assert(res.send(:paramcheck, :name), "Did not allow name") - klass.expects(:valid_parameter?).with("title").returns(false) - assert(res.send(:paramcheck, :title), "Did not allow title") - - # It's not actually allowed - klass.expects(:valid_parameter?).with("other").returns(false) - res.expects(:fail) - ref.expects(:type) - res.send(:paramcheck, :other) - end - - def test_evaluate - # First try the most common case, we're not a builtin type. - res = mkresource - ref = res.instance_variable_get("@ref") - type = mock("type") - ref.expects(:definedtype).returns(type) - res.expects(:finish) - res.scope = mock("scope") - - type.expects(:evaluate_code).with(res) - - res.evaluate - end - - def test_proxymethods - res = Parser::Resource.new :type => "evaltest", :title => "yay", - :source => mock("source"), :scope => mkscope - - assert_equal("Evaltest", res.type) - assert_equal("yay", res.title) - assert_equal(false, res.builtin?) - end - - # This is a bit of a weird one -- the user should not actually know - # that components exist, so we want references to act like they're not - # builtin - def test_components_are_not_builtin - ref = Parser::Resource::Reference.new(:type => "component", :title => "yay") - - assert_nil(ref.builtintype, "Definition was considered builtin") - end - - # The second part of #539 - make sure resources pass the arguments - # correctly. - def test_title_with_definitions - parser = mkparser - define = parser.newdefine "yayness", - :code => resourcedef("file", "/tmp", - "owner" => varref("name"), "mode" => varref("title")) - - - klass = parser.find_hostclass("", "") - should = {:name => :owner, :title => :mode} - [ - {:name => "one", :title => "two"}, - {:title => "three"}, - ].each do |hash| - config = mkcompiler parser - args = {:type => "yayness", :title => hash[:title], - :source => klass, :scope => config.topscope} - if hash[:name] - args[:params] = {:name => hash[:name]} - else - args[:params] = {} # override the defaults - end - - res = nil - assert_nothing_raised("Could not create res with %s" % hash.inspect) do - res = mkresource(args) - end - assert_nothing_raised("Could not eval res with %s" % hash.inspect) do - res.evaluate - end - - made = config.topscope.findresource("File[/tmp]") - assert(made, "Did not create resource with %s" % hash.inspect) - should.each do |orig, param| - assert_equal(hash[orig] || hash[:title], made[param], - "%s was not set correctly with %s" % [param, hash.inspect]) - end - end - end - - # part of #629 -- the undef keyword. Make sure 'undef' params get skipped. - def test_undef_and_to_hash - res = mkresource :type => "file", :title => "/tmp/testing", - :source => mock("source"), :scope => mkscope, - :params => {:owner => :undef, :mode => "755"} - - hash = nil - assert_nothing_raised("Could not convert resource with undef to hash") do - hash = res.to_hash - end - - assert_nil(hash[:owner], "got a value for an undef parameter") - end -end diff --git a/test/language/scope.rb b/test/language/scope.rb index 8819de66e..b1ba63de4 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -20,6 +20,11 @@ class TestScope < Test::Unit::TestCase include PuppetTest::ParserTesting include PuppetTest::ResourceTesting + def setup + Puppet::Node::Environment.clear + super + end + def to_ary(hash) hash.collect { |key,value| [key,value] @@ -102,60 +107,6 @@ class TestScope < Test::Unit::TestCase } end - def test_setdefaults - config = mkcompiler - - scope = config.topscope - - defaults = scope.instance_variable_get("@defaults") - - # First the case where there are no defaults and we pass a single param - param = stub :name => "myparam", :file => "f", :line => "l" - scope.setdefaults(:mytype, param) - assert_equal({"myparam" => param}, defaults[:mytype], "Did not set default correctly") - - # Now the case where we pass in multiple parameters - param1 = stub :name => "one", :file => "f", :line => "l" - param2 = stub :name => "two", :file => "f", :line => "l" - scope.setdefaults(:newtype, [param1, param2]) - assert_equal({"one" => param1, "two" => param2}, defaults[:newtype], "Did not set multiple defaults correctly") - - # And the case where there's actually a conflict. Use the first default for this. - newparam = stub :name => "myparam", :file => "f", :line => "l" - 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 - - def test_lookupdefaults - config = mkcompiler - top = config.topscope - - # Make a subscope - sub = config.newscope(top) - - topdefs = top.instance_variable_get("@defaults") - subdefs = sub.instance_variable_get("@defaults") - - # First add some defaults to our top scope - topdefs[:t1] = {:p1 => :p2, :p3 => :p4} - topdefs[:t2] = {:p5 => :p6} - - # Then the sub scope - subdefs[:t1] = {:p1 => :p7, :p8 => :p9} - subdefs[:t2] = {:p5 => :p10, :p11 => :p12} - - # 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 - def test_parent config = mkcompiler top = config.topscope @@ -167,86 +118,6 @@ class TestScope < Test::Unit::TestCase assert_equal(top, sub.parent, "Did not find parent scope on second call") end - def test_strinterp - # Make and evaluate our classes so the qualified lookups work - parser = mkparser - klass = parser.newclass("") - scope = mkscope(:parser => parser) - Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => scope, :source => mock('source')).evaluate - - assert_nothing_raised { - scope.setvar("test","value") - } - - scopes = {"" => scope} - - %w{one one::two one::two::three}.each do |name| - klass = parser.newclass(name) - Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => scope, :source => mock('source')).evaluate - scopes[name] = scope.compiler.class_scope(klass) - scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,'')) - end - - assert_equal("value", scope.lookupvar("::test"), "did not look up qualified value correctly") - tests = { - "string ${test}" => "string value", - "string ${one::two::three::test}" => "string value-three", - "string $one::two::three::test" => "string value-three", - "string ${one::two::test}" => "string value-two", - "string $one::two::test" => "string value-two", - "string ${one::test}" => "string value-one", - "string $one::test" => "string value-one", - "string ${::test}" => "string value", - "string $::test" => "string value", - "string ${test} ${test} ${test}" => "string value value value", - "string $test ${test} $test" => "string value value value", - "string \\$test" => "string $test", - '\\$test string' => "$test string", - '$test string' => "value string", - 'a testing $' => "a testing $", - 'a testing \$' => "a testing $", - "an escaped \\\n carriage return" => "an escaped carriage return", - '\$' => "$", - '\s' => "\s", - '\t' => "\t", - '\n' => "\n" - } - - tests.each do |input, output| - assert_nothing_raised("Failed to scan %s" % input.inspect) do - assert_equal(output, scope.strinterp(input), - 'did not parserret %s correctly' % input.inspect) - end - end - - logs = [] - Puppet::Util::Log.close - Puppet::Util::Log.newdestination(logs) - - # #523 - %w{d f h l w z}.each do |l| - string = "\\" + l - assert_nothing_raised do - assert_equal(string, scope.strinterp(string), - 'did not parserret %s correctly' % string) - end - - assert(logs.detect { |m| m.message =~ /Unrecognised escape/ }, - "Did not get warning about escape sequence with %s" % string) - logs.clear - end - end - - def test_tagfunction - Puppet::Parser::Functions.function(:tag) - scope = mkscope - resource = mock 'resource' - scope.resource = resource - resource.expects(:tag).with("yayness", "booness") - - scope.function_tag(%w{yayness booness}) - end - def test_includefunction parser = mkparser scope = mkscope :parser => parser @@ -270,7 +141,7 @@ class TestScope < Test::Unit::TestCase [myclass, otherclass].each do |klass| assert(scope.compiler.class_scope(klass), - "%s was not set" % klass.classname) + "%s was not set" % klass.name) end end @@ -312,13 +183,14 @@ class TestScope < Test::Unit::TestCase # components. def test_virtual_definitions_do_not_get_evaluated config = mkcompiler - parser = config.parser + parser = mkparser # Create a default source - config.topscope.source = parser.newclass "" + parser.newclass("") + config.topscope.source = parser.known_resource_types.hostclass("") # And a scope resource - scope_res = stub 'scope_resource', :virtual? => true, :exported? => false, :tags => [], :builtin? => true, :type => "eh", :title => "bee" + scope_res = Puppet::Parser::Resource.new(:file, "/file", :scope => "scope", :source => "source") config.topscope.resource = scope_res args = AST::ASTArray.new( @@ -374,20 +246,13 @@ include yay @@host { puppet: ip => \"192.168.0.3\" } Host <<||>>" - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new - } - config = 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} + node.merge "hostname" => node.name 2.times { |i| - assert_nothing_raised { - config = interp.compile(node) - } + config = Puppet::Parser::Compiler.new(node).compile flat = config.extract.flatten @@ -418,54 +283,6 @@ Host <<||>>" "Did not add extra namespace correctly") end - def test_find_hostclass_and_find_definition - parser = mkparser - - # Make sure our scope calls the parser find_hostclass method with - # the right namespaces - scope = mkscope :parser => parser - - parser.metaclass.send(:attr_accessor, :last) - - methods = [:find_hostclass, :find_definition] - methods.each do |m| - parser.meta_def(m) do |namespace, name| - @checked ||= [] - @checked << [namespace, name] - - # Only return a value on the last call. - if @last == namespace - ret = @checked.dup - @checked.clear - return ret - else - return nil - end - end - end - - test = proc do |should| - parser.last = scope.namespaces[-1] - methods.each do |method| - result = scope.send(method, "testing") - assert_equal(should, result, - "did not get correct value from %s with namespaces %s" % - [method, scope.namespaces.inspect]) - end - end - - # Start with the empty namespace - assert_nothing_raised { test.call([["", "testing"]]) } - - # Now add a namespace - scope.add_namespace("a") - assert_nothing_raised { test.call([["a", "testing"]]) } - - # And another - scope.add_namespace("b") - assert_nothing_raised { test.call([["a", "testing"], ["b", "testing"]]) } - end - # #629 - undef should be "" or :undef def test_lookupvar_with_undef scope = mkscope diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index dee38eb3a..44c78f2c3 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -47,9 +47,8 @@ module PuppetTest::ParserTesting end def mkcompiler(parser = nil) - parser ||= mkparser node = mknode - return Compiler.new(node, parser) + return Compiler.new(node) end def mknode(name = nil) @@ -59,12 +58,9 @@ module PuppetTest::ParserTesting Puppet::Node.new(name) end - def mkinterp - Puppet::Parser::Interpreter.new - end - - def mkparser(args = {}) - Puppet::Parser::Parser.new(args) + def mkparser + Puppet::Node::Environment.clear + Puppet::Parser::Parser.new(Puppet::Node::Environment.new) end def mkscope(hash = {}) @@ -306,13 +302,10 @@ module PuppetTest::ParserTesting interp = nil oldmanifest = Puppet[:manifest] Puppet[:manifest] = manifest - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new - } trans = nil assert_nothing_raised { - trans = interp.compile(mknode) + trans = Puppet::Parser::Compiler.new(mknode).compile } config = nil diff --git a/test/lib/puppettest/resourcetesting.rb b/test/lib/puppettest/resourcetesting.rb index d4469a203..95fe5bcb7 100644 --- a/test/lib/puppettest/resourcetesting.rb +++ b/test/lib/puppettest/resourcetesting.rb @@ -15,9 +15,12 @@ module PuppetTest::ResourceTesting args[:source] ||= "source" args[:scope] ||= mkscope - {:type => "resource", :title => "testing", - :source => "source", :scope => "scope"}.each do |param, value| - args[param] ||= value + type = args[:type] || "resource" + title = args[:title] || "testing" + args.delete(:type) + args.delete(:title) + {:source => "source", :scope => "scope"}.each do |param, value| + args[param] ||= value end params = args[:params] || {:one => "yay", :three => "rah"} @@ -27,7 +30,7 @@ module PuppetTest::ResourceTesting args[:params] = paramify args[:source], params end - Parser::Resource.new(args) + Parser::Resource.new(type, title, args) end def param(name, value, source) diff --git a/test/other/relationships.rb b/test/other/relationships.rb index b15ff5062..e9d3a9376 100755 --- a/test/other/relationships.rb +++ b/test/other/relationships.rb @@ -80,7 +80,7 @@ class TestRelationships < Test::Unit::TestCase # Testing #411. It was a problem with builddepends. def test_missing_deps - file = Puppet::Type.type(:file).new :path => tempfile, :require => Puppet::Resource::Reference.new("file", "/no/such/file") + file = Puppet::Type.type(:file).new :path => tempfile, :require => Puppet::Resource.new("file", "/no/such/file") assert_raise(Puppet::Error) do file.builddepends diff --git a/test/other/transactions.rb b/test/other/transactions.rb index 94deeab26..6f4f5d913 100755 --- a/test/other/transactions.rb +++ b/test/other/transactions.rb @@ -125,12 +125,12 @@ class TestTransactions < Test::Unit::TestCase file = Puppet::Type.type(:file).new(:title => "file", :path => path, :content => "yayness") first = Puppet::Type.type(:exec).new(:title => "first", :command => "/bin/echo first > #{firstpath}", - :subscribe => Puppet::Resource::Reference.new(:file, path), + :subscribe => Puppet::Resource.new(:file, path), :refreshonly => true ) second = Puppet::Type.type(:exec).new(:title => "second", :command => "/bin/echo second > #{secondpath}", - :subscribe => Puppet::Resource::Reference.new(:exec, "first"), + :subscribe => Puppet::Resource.new(:exec, "first"), :refreshonly => true ) @@ -218,7 +218,7 @@ class TestTransactions < Test::Unit::TestCase @@tmpfiles << execfile # 'subscribe' expects an array of arrays - exec[:subscribe] = Puppet::Resource::Reference.new(file.class.name,file.name) + exec[:subscribe] = Puppet::Resource.new(file.class.name,file.name) exec[:refreshonly] = true assert_nothing_raised() { @@ -302,13 +302,13 @@ class TestTransactions < Test::Unit::TestCase :path => ENV["PATH"], :command => "touch %s" % file1, :refreshonly => true, - :subscribe => Puppet::Resource::Reference.new(:file, path) + :subscribe => Puppet::Resource.new(:file, path) ) exec2 = Puppet::Type.type(:exec).new( :path => ENV["PATH"], :command => "touch %s" % file2, :refreshonly => true, - :subscribe => Puppet::Resource::Reference.new(:file, path) + :subscribe => Puppet::Resource.new(:file, path) ) assert_apply(file, exec1, exec2) @@ -361,7 +361,7 @@ class TestTransactions < Test::Unit::TestCase :name => "touch %s" % fname, :path => "/usr/bin:/bin", :schedule => "monthly", - :subscribe => Puppet::Resource::Reference.new("file", file.name) + :subscribe => Puppet::Resource.new("file", file.name) ) config = mk_catalog(file, exec) diff --git a/test/ral/type/exec.rb b/test/ral/type/exec.rb index c533aff1c..27a3de4d1 100755 --- a/test/ral/type/exec.rb +++ b/test/ral/type/exec.rb @@ -181,7 +181,7 @@ class TestExec < Test::Unit::TestCase exec = Puppet::Type.type(:exec).new( :command => oexe, - :require => Puppet::Resource::Reference.new(:file, oexe) + :require => Puppet::Resource.new(:file, oexe) ) comp = mk_catalog("Testing", file, exec) @@ -404,7 +404,7 @@ class TestExec < Test::Unit::TestCase :path => basedir, :recurse => true, :mode => "755", - :require => Puppet::Resource::Reference.new("exec", "mkdir") + :require => Puppet::Resource.new("exec", "mkdir") ) } |
