diff options
| author | Luke Kanies <luke@reductivelabs.com> | 2010-01-29 20:57:21 -0600 |
|---|---|---|
| committer | test branch <puppet-dev@googlegroups.com> | 2010-02-17 06:50:53 -0800 |
| commit | 7089446697ad550c22012bc2b5572030727d67e1 (patch) | |
| tree | 40d160f11839fe6e20311186ded4e621d23e1242 /lib | |
| parent | 4871c909cd28c82b64d0b62d8a27e62737d8733d (diff) | |
| download | puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.gz puppet-7089446697ad550c22012bc2b5572030727d67e1.tar.xz puppet-7089446697ad550c22012bc2b5572030727d67e1.zip | |
Removing Resource::Reference classes
This commit is hopefully less messy than it
first appears, but it's certainly cross-cutting.
The reason for all of this is that we previously only
looked up builtin resource types from outside the parser,
but now that the defined resource types are available globally
via environments, we can push that lookup code to Resource.
Once we do that, however, we have to have environment and
namespace information in every resource.
Here I remove the Resource::Reference classes (except
the AST class), and use Resource instances instead. I
did this because the shared code between the two classes
got incredibly complicated, such that they should have had
a hierarchical relationship disallowed by their constants.
This complexity convinced me just to get rid of References
entirely.
I also make Puppet::Parser::Resource a subclass
of Puppet::Resource.
There are still broken tests in test/, but this was a big
enough commit I wanted to get it in.
Signed-off-by: Luke Kanies <luke@reductivelabs.com>
Diffstat (limited to 'lib')
23 files changed, 204 insertions, 448 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 |
