diff options
Diffstat (limited to 'lib/puppet/parser/resource.rb')
-rw-r--r-- | lib/puppet/parser/resource.rb | 319 |
1 files changed, 164 insertions, 155 deletions
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 371f56ec1..eace88645 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -10,9 +10,9 @@ class Puppet::Parser::Resource include Puppet::Util::Logging attr_accessor :source, :line, :file, :scope, :rails_id - attr_accessor :virtual, :override, :params, :translated + attr_accessor :virtual, :override, :translated - attr_reader :exported + attr_reader :exported, :evaluated, :params attr_writer :tags @@ -24,7 +24,7 @@ class Puppet::Parser::Resource end # Set up some boolean test methods - [:exported, :translated, :override].each do |method| + [:exported, :translated, :override, :virtual, :evaluated].each do |method| newmeth = (method.to_s + "?").intern define_method(newmeth) do self.send(method) @@ -43,47 +43,6 @@ class Puppet::Parser::Resource end end - # Add default values from our definition. - def adddefaults - defaults = scope.lookupdefaults(self.type) - - defaults.each do |name, param| - unless @params.include?(param.name) - self.debug "Adding default for %s" % param.name - - @params[param.name] = param - end - end - end - - # Add any metaparams defined in our scope. This actually adds any metaparams - # from any parent scope, and there's currently no way to turn that off. - def addmetaparams - Puppet::Type.eachmetaparam do |name| - next if self[name] - if val = scope.lookupvar(name.to_s, false) - unless val == :undefined - set Param.new(:name => name, :value => val, - :source => scope.source) - end - end - end - end - - # Add any overrides for this object. - def addoverrides - overrides = scope.configuration.resource_overrides(self) - raise "fix this test" - - overrides.each do |over| - self.merge(over) - end - - # Remove the overrides, so that the configuration knows there - # are none left. - overrides.clear - end - def builtin=(bool) @ref.builtin = bool end @@ -92,7 +51,7 @@ class Puppet::Parser::Resource def evaluate if klass = @ref.definedtype finish() - scope.deleteresource(self) + scope.configuration.delete_resource(self) return klass.evaluate(:scope => scope, :type => self.type, :title => self.title, @@ -110,6 +69,8 @@ class Puppet::Parser::Resource @evaluated = true end + # Mark this resource as both exported and virtual, + # or remove the exported mark. def exported=(value) if value @virtual = true @@ -119,63 +80,71 @@ class Puppet::Parser::Resource end end - def evaluated? - if defined? @evaluated and @evaluated - true - else - false - end - end - # Do any finishing work on this object, called before evaluation or # before storage/translation. def finish - addoverrides() - adddefaults() - addmetaparams() + add_overrides() + add_defaults() + add_metaparams() + validate() end def initialize(options) - options = symbolize_options(options) - - # Collect the options necessary to make the reference. - refopts = [:type, :title].inject({}) do |hash, param| - hash[param] = options[param] - options.delete(param) - hash + # Set all of the options we can. + options.each do |option, value| + if respond_to?(option.to_s + "=") + send(option.to_s + "=", value) + options.delete(option) + end end - @params = {} - tmpparams = nil - if tmpparams = options[:params] - options.delete(:params) + [:scope, :source].each do |attribute| + unless self.send(attribute) + raise ArgumentError, "Resources require a %s" % attribute + end end - # Now set the rest of the options. - set_options(options) - - @ref = Reference.new(refopts) + # Set up our reference. + if type = options[:type] and title = options[:title] + options.delete(:type) + options.delete(:title) + else + raise ArgumentError, "Resources require a type and title" + end - requiredopts(:scope, :source) + @ref = Reference.new(:type => type, :title => title, :scope => self.scope) - @ref.scope = self.scope + @params = {} - if tmpparams - tmpparams.each do |param| - # We use the method here, because it does type-checking. - set(param) + # Define all of the parameters + if params = options[:params] + options.delete(:params) + params.each do |param| + set_parameter(param) end end + + # Throw an exception if we've got any arguments left to set. + unless options.empty? + raise ArgumentError, "Resources do not accept %s" % options.keys.collect { |k| k.to_s }.join(", ") + end end - # Merge an override resource in. + # Merge an override resource in. This will throw exceptions if + # any overrides aren't allowed. def merge(resource) + # Test the resource scope, to make sure the resource is even allowed + # to override. + unless self.source.object_id == resource.source.object_id || resource.source.child_of?(self.source) + raise Puppet::ParseError.new("Only subclasses can override parameters", resource.line, resource.file) + end # Some of these might fail, but they'll fail in the way we want. resource.params.each do |name, param| - set(param) + override_parameter(param) end end + # Modify this resource in the Rails database. Poor design, yo. def modify_rails(db_resource) args = rails_args args.each do |param, value| @@ -226,23 +195,6 @@ class Puppet::Parser::Resource @@paramcheck end - # Verify that all passed parameters are valid. This throws an error if - # there's a problem, so we don't have to worry about the return value. - def paramcheck(param) - param = param.to_s - # Now make sure it's a valid argument to our class. These checks - # are organized in order of commonhood -- most types, it's a valid - # argument and paramcheck is enabled. - if @ref.typeclass.validattr?(param) - true - elsif %w{name title}.include?(param) # always allow these - true - elsif paramcheck? - self.fail Puppet::ParseError, "Invalid parameter '%s' for type '%s'" % - [param.inspect, @ref.type] - end - end - # A temporary occasion, until I get paths in the scopes figured out. def path to_s @@ -253,59 +205,6 @@ class Puppet::Parser::Resource @ref.to_s end - # You have to pass a Resource::Param to this. - def set(param, value = nil, source = nil) - if value and source - param = Puppet::Parser::Resource::Param.new( - :name => param, :value => value, :source => source - ) - elsif ! param.is_a?(Puppet::Parser::Resource::Param) - raise ArgumentError, "Must pass a parameter or all necessary values" - end - # Because definitions are now parse-time, I can paramcheck immediately. - paramcheck(param.name) - - if current = @params[param.name] - # This is where we'd ignore any equivalent values if we wanted to, - # but that would introduce a lot of really bad ordering issues. - if param.source.child_of?(current.source) - if param.add - # Merge with previous value. - param.value = [ current.value, param.value ].flatten - end - - # Replace it, keeping all of its info. - @params[param.name] = param - else - if Puppet[:trace] - puts caller - end - msg = "Parameter '%s' is already set on %s" % - [param.name, self.to_s] - if current.source.to_s != "" - msg += " by %s" % current.source - end - if current.file or current.line - fields = [] - fields << current.file if current.file - fields << current.line.to_s if current.line - msg += " at %s" % fields.join(":") - end - msg += "; cannot redefine" - error = Puppet::ParseError.new(msg) - error.file = param.file if param.file - error.line = param.line if param.line - raise error - end - else - if self.source == param.source or param.source.child_of?(self.source) - @params[param.name] = param - else - fail Puppet::ParseError, "Only subclasses can set parameters" - end - end - end - def tags unless defined? @tags @tags = scope.tags @@ -387,12 +286,102 @@ class Puppet::Parser::Resource return obj end - - def virtual? - self.virtual - end private + + # Add default values from our definition. + def add_defaults + scope.lookupdefaults(self.type).each do |name, param| + unless @params.include?(name) + self.debug "Adding default for %s" % name + + @params[name] = param + end + end + end + + # Add any metaparams defined in our scope. This actually adds any metaparams + # from any parent scope, and there's currently no way to turn that off. + def add_metaparams + Puppet::Type.eachmetaparam do |name| + # Skip metaparams that we already have defined. + next if @params[name] + if val = scope.lookupvar(name.to_s, false) + unless val == :undefined + set_parameter(name, val) + end + end + end + end + + # Add any overrides for this object. + def add_overrides + if overrides = scope.configuration.resource_overrides(self) + overrides.each do |over| + self.merge(over) + end + + # Remove the overrides, so that the configuration knows there + # are none left. + overrides.clear + end + end + + # Accept a parameter from an override. + def override_parameter(param) + # This can happen if the override is defining a new parameter, rather + # than replacing an existing one. + unless current = @params[param.name] + @params[param.name] = param + return + end + + # The parameter is already set. See if they're allowed to override it. + if param.source.child_of?(current.source) + if param.add + # Merge with previous value. + param.value = [ current.value, param.value ].flatten + end + + # Replace it, keeping all of its info. + @params[param.name] = param + else + if Puppet[:trace] + puts caller + end + msg = "Parameter '%s' is already set on %s" % + [param.name, self.to_s] + if current.source.to_s != "" + msg += " by %s" % current.source + end + if current.file or current.line + fields = [] + fields << current.file if current.file + fields << current.line.to_s if current.line + msg += " at %s" % fields.join(":") + end + msg += "; cannot redefine" + raise Puppet::ParseError.new(msg, param.line, param.file) + end + end + + # Verify that all passed parameters are valid. This throws an error if + # there's a problem, so we don't have to worry about the return value. + def paramcheck(param) + param = param.to_s + # Now make sure it's a valid argument to our class. These checks + # are organized in order of commonhood -- most types, it's a valid + # argument and paramcheck is enabled. + if @ref.typeclass.validattr?(param) + true + elsif %w{name title}.include?(param) # always allow these + true + elsif paramcheck? + self.fail Puppet::ParseError, "Invalid parameter '%s' for type '%s'" % + [param, @ref.type] + end + end + def rails_args return [:type, :title, :line, :exported].inject({}) do |hash, param| # 'type' isn't a valid column name, so we have to use another name. @@ -403,6 +392,26 @@ class Puppet::Parser::Resource hash end end -end -# $Id$ + # Define a parameter in our resource. + def set_parameter(param, value = nil) + if value + param = Puppet::Parser::Resource::Param.new( + :name => param, :value => value, :source => self.source + ) + elsif ! param.is_a?(Puppet::Parser::Resource::Param) + raise ArgumentError, "Must pass a parameter or all necessary values" + end + + # And store it in our parameter hash. + @params[param.name] = param + end + + # Make sure the resource's parameters are all valid for the type. + def validate + @params.each do |name, param| + # Make sure it's a valid parameter. + paramcheck(name) + end + end +end |