diff options
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") ) } |
