diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-03 15:41:39 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-03 15:41:39 +0000 |
| commit | e2e2fb3f2a771cca16e64cb027615e979fa8d586 (patch) | |
| tree | 84ecca73bb12048d3cb914d03c1f4f0e74a484ae /lib | |
| parent | 5302921b2e3698f864c2955a67dd9779c8aea18b (diff) | |
| download | puppet-e2e2fb3f2a771cca16e64cb027615e979fa8d586.tar.gz puppet-e2e2fb3f2a771cca16e64cb027615e979fa8d586.tar.xz puppet-e2e2fb3f2a771cca16e64cb027615e979fa8d586.zip | |
some updates to the typegen stuff, even though i may still not use it
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@763 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/puppet/type/typegen.rb | 43 | ||||
| -rw-r--r-- | lib/puppet/type/typegen/filerecord.rb | 174 | ||||
| -rw-r--r-- | lib/puppet/type/typegen/filetype.rb | 227 |
3 files changed, 164 insertions, 280 deletions
diff --git a/lib/puppet/type/typegen.rb b/lib/puppet/type/typegen.rb index 46008bcb3..d0a55e081 100644 --- a/lib/puppet/type/typegen.rb +++ b/lib/puppet/type/typegen.rb @@ -1,11 +1,8 @@ - -# parse and write configuration files using objects with minimal parsing abilities - require 'etc' require 'puppet/type' module Puppet - class Type +class Type class TypeGenerator < Puppet::Type include Enumerable @@ -19,57 +16,31 @@ class TypeGenerator < Puppet::Type @paramdoc[:name] = "..." - #--------------------------------------------------------------- - def TypeGenerator.[](name) - return @subclasses[name] + class << self + attr_accessor :name end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def TypeGenerator.inherited(subclass) - #subclass.initvars - super(subclass) + def TypeGenerator.[](name) + return @subclasses[name] end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - # we don't need to 'super' here because type.rb already runs initvars - # in Type#inherited def TypeGenerator.initvars @subclasses = Hash.new(nil) super end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - def TypeGenerator.name - return @name - end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - def TypeGenerator.name=(name) - @name = name - end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def TypeGenerator.namevar return @namevar || :name end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def TypeGenerator.namevar=(namevar) - debug "Setting namevar for %s to %s" % [self,namevar] + Puppet.debug "Setting namevar for %s to %s" % [self,namevar] unless namevar.is_a? Symbol namevar = namevar.intern end @namevar = namevar end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def TypeGenerator.newtype(arghash) unless defined? @parameters raise "Type %s is set up incorrectly" % self @@ -139,9 +110,7 @@ class TypeGenerator < Puppet::Type Puppet::Type.buildtypehash return klass end - #--------------------------------------------------------------- end -#--------------------------------------------------------------- end end diff --git a/lib/puppet/type/typegen/filerecord.rb b/lib/puppet/type/typegen/filerecord.rb index 6cf80f588..6e502c170 100644 --- a/lib/puppet/type/typegen/filerecord.rb +++ b/lib/puppet/type/typegen/filerecord.rb @@ -5,78 +5,67 @@ require 'etc' require 'puppet/type' require 'puppet/type/typegen' -#--------------------------------------------------------------- class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator - attr_accessor :fields, :namevar, :splitchar, :object + class << self + # The name of the record type. Probably superfluous. + attr_accessor :name - @parameters = [:name, :splitchar, :fields, :namevar, :filetype, :regex, :joinchar] - @abstract = true - @metaclass = true + # What character we split on to convert from a line into a set of fields. + # This can be either a string or a regex and defaults to /\s+/ + attr_accessor :fieldsep - @namevar = :name - @name = :filerecord + # The fields in this record type. + attr_accessor :fields - #--------------------------------------------------------------- - def FileRecord.newtype(hash) - #shortname = hash[:name] - #hash[:name] = hash[:filetype].name.capitalize + hash[:name].capitalize - klass = super(hash) - #klass.name = shortname - klass.parameters = hash[:fields] - #klass.namevar = hash[:namevar] - klass.filetype = hash[:filetype] - hash.delete(:fields) - hash.delete(:namevar) - return klass - end - #--------------------------------------------------------------- + # Which of the fields counts as the name of the record. Defaults to the + # first field. + attr_accessor :namevar - #--------------------------------------------------------------- - def FileRecord.fields=(ary) - @fields = ary - end - #--------------------------------------------------------------- + # Which filetype this record type is associated with. Essentially useless. + attr_accessor :filetype - #--------------------------------------------------------------- - def FileRecord.fields - return @fields - end - #--------------------------------------------------------------- + # An optional regex to use to match fields. This can be used instead + # of splitting based on a character and must use match sets to return + # the fields. If this is not set, then a regex is created from the + # fieldsep. If your regex is complicated enough that you have nested + # parentheses, then just set your fields up so that the non-field matches + # are nil. + attr_writer :regex - #--------------------------------------------------------------- - def FileRecord.filetype - @filetype - end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - def FileRecord.filetype=(filetype) - if filetype.is_a?(String) - @filetype = Puppet::Type::FileType[filetype] - elsif filetype.is_a?(Puppet::Type::FileType) - @filetype = filetype - else - raise "Cannot use objects of type %s as filetypes" % filetype - end - end - #--------------------------------------------------------------- + # The character(s) to use to join the records back together. If this is + # not set, then 'fieldsep' will be used instead, which means that this + # *must* be set if 'fieldsep' is a regex or if the record regex is set. + attr_accessor :fieldjoin - #--------------------------------------------------------------- - def FileRecord.joinchar=(char) - @joinchar = char + # Some records (like cron jobs) don't have a name field, so we have to + # store the name in the previous comment. Dern. If we are doing this, + # it is assumed that some objects won't yet have names, so we'll generate + # names for those cases. + attr_accessor :extname end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileRecord.joinchar - unless defined? @joinchar - @joinchar = nil + def FileRecord.newtype(hash) + # Provide some defaults. + newklass = Class.new(self) + + # If they've passed in values, then set them appropriately. + unless hash.empty? + hash.each { |param, val| + meth = param.to_s + "=" + if self.respond_to? meth + self.send(meth, val) + end + } + end + + # If they've provided a block, then yield to it + if block_given? + yield newklass end - @joinchar + + return newklass end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def FileRecord.match(object,line) matchobj = nil begin @@ -93,30 +82,24 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator return child end end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - def FileRecord.regex=(regex) - @regex = regex - end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def FileRecord.regex - # the only time @regex is allowed to be nil is if @splitchar is defined + # the only time @regex is allowed to be nil is if @fieldsep is defined if @regex.nil? - if @splitchar.nil? - raise "%s defined incorrectly -- splitchar or regex must be specified" % + if @fieldsep.nil? + raise Puppet::DevError, + "%s defined incorrectly -- fieldsep or regex must be specified" % self else ary = [] text = @fields.collect { |field| - "([^%s]*)" % @splitchar - }.join(@splitchar) + "([^%s]*)" % @fieldsep + }.join(@fieldsep) begin @regex = Regexp.new(text) rescue RegexpError => detail - raise "Could not create splitregex from %s" % @splitchar + raise Puppet::DevError, + "Could not create splitregex from %s" % @fieldsep end debug("Created regexp %s" % @regex) end @@ -124,39 +107,12 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator begin @regex = Regexp.new(@regex) rescue RegexpError => detail - raise "Could not create splitregex from %s" % @regex + raise Puppet::DevError, "Could not create splitregex from %s" % @regex end end return @regex end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - def FileRecord.splitchar=(char) - @splitchar = char - #@regex = %r{#{char}} - end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileRecord.splitchar - return @splitchar - end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - #def [](field) - # @parameters[field] - #end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - #def []=(field,value) - # @parameters[field] = value - #end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- def ==(other) unless self.class == other.class return false @@ -173,9 +129,7 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator } return true end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def initialize(hash) if self.class == Puppet::Type::FileRecord self.class.newtype(hash) @@ -187,9 +141,7 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator #end super(hash) end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def match=(matchobj) @match = matchobj #puts "captures are [%s]" % [matchobj.captures] @@ -198,13 +150,11 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator #puts "%s => %s" % [field,@parameters[field]] } end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def record=(record) begin ary = record.split(self.class.regex) - rescue RegexpError=> detail + rescue RegexpError => detail raise RegexpError.new(detail) end self.class.fields.each { |field| @@ -212,9 +162,7 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator #puts "%s => %s" % [field,@parameters[field]] } end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def name if @parameters.include?(self.class.namevar) return @parameters[self.class.namevar] @@ -223,9 +171,7 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator [self.class.namevar,self.class.to_s] end end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def to_s ary = self.class.fields.collect { |field| if ! @parameters.include?(field) @@ -233,10 +179,8 @@ class Puppet::Type::FileRecord < Puppet::Type::TypeGenerator else @parameters[field] end - }.join(self.class.joinchar || self.class.splitchar) + }.join(self.class.fieldjoin || self.class.fieldsep) end - #--------------------------------------------------------------- end -#--------------------------------------------------------------- # $Id$ diff --git a/lib/puppet/type/typegen/filetype.rb b/lib/puppet/type/typegen/filetype.rb index 22424c36d..c7ed89b25 100644 --- a/lib/puppet/type/typegen/filetype.rb +++ b/lib/puppet/type/typegen/filetype.rb @@ -1,150 +1,145 @@ - # parse and write configuration files using objects with minimal parsing abilities require 'puppet/type' require 'puppet/type/typegen' class Puppet::Type::FileType < Puppet::Type::TypeGenerator - attr_accessor :childtype - - @parameters = [:name, :linesplit, :escapednewlines] - #@abstract = true - @metaclass = true + @parameters = [:name, :recordsep, :escapednewlines] @namevar = :name @name = :filetype @modsystem = true - #--------------------------------------------------------------- - def FileType.newtype(hash) - unless hash.include?(:linesplit) - hash[:linesplit] = "\n" - end + class << self + # Which field in the record functions as the name of the record. + attr_accessor :namevar + + # Does this filetype support escaped newlines? Defaults to false. + attr_accessor :escapednewlines + + # What do comments in this filetype look like? Defaults to /^#|^\s/ + attr_accessor :comment - # i don't think there's any reason to 'super' this - #klass = Puppet::Type::TypeGenerator.newtype(hash) - klass = super(hash) - - klass.escapednewlines = true - klass.namevar = :name - klass.parameters = [:name, :path, :complete] - - #klass.childtype = Puppet::Type::FileRecord.newtype( - # :name => hash[:name] + "_record", - # :splitchar => hash[:recordsplit], - # :fields => hash[:fields], - # :namevar => hash[:namevar] - #) - #klass.addrecord( - # :name => hash[:name] + "_record", - # :splitchar => hash[:recordsplit], - # :fields => hash[:fields], - # :namevar => hash[:namevar] - #) - - return klass + # What is the record separator? Defaults to "\n". + attr_accessor :recordsep + + # How do we separate records? Normally we just turn the recordsep + # into a regex, but you can override that, or just not use the recordsep. + attr_writer :regex end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - # currently not used - def FileType.addrecord(hash) - unless defined? @records - @records = {} + # Add a new record to our filetype. This should never be called on the FileType + # class itself, only on its subclasses. + def FileType.addrecord(hash = {}) + if self == Puppet::Type::FileRecord + raise Puppet::DevError, "Cannot add records to the FileType base class" + end + + newrecord = Puppet::Type::FileRecord.newtype(hash) + newrecord.filetype = self + + if block_given? + yield newrecord end - hash[:filetype] = self - - # default to the naming field being the first field provided - unless hash.include?(:namevar) - hash[:namevar] = hash[:fields][0] + + unless defined? @records + @records = [] end - recordtype = Puppet::Type::FileRecord.newtype(hash) - @records[recordtype.name] = recordtype + @records << newrecord end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.records - return @records + # Remove all defined filetypes. Mostly used for testing. + def self.clear + if defined? @subclasses + @subclasses.each { |sub| + sub.clear + } + @subclasses.clear + end + + if defined? @records + @records.clear + end end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.escapednewlines=(value) - @escnlines = value + # Yield each record in turn, so we can iterate over each of them. + def self.eachrecord + @records.each { |record| + yield record + } end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.escapednewlines - if ! defined? @escnlines or @escnlines.nil? - return false - else - return @escnlines + # Create a new file type. You would generally provide an initialization block + # for this method: + # + # FileType.newtype do |type| + # @name = "cron" + # type.addrecord do |record| + # @name = "cronjob" + # @splitchar = "\t" + # @fields = [:minute, :hour, :monthday, :month, :weekday, :command] + # end + # end + # + # You don't actually have to provide anything at initialization time, but your + # filetype won't be much use if you don't at least provide it with some record + # types. You will generally only have one record type, since comments are + # handled transparently, although you might have to define what looks like a + # comment (the default is anything starting with a '#' or any whitespace). + def FileType.newtype(hash = {}) + unless defined? @subclasses + @subclasses = Hash.new end - end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.childtype - unless defined? @childtype - @childtype = nil + # Provide some defaults. + newklass = Class.new(self) do + @escapednewlines = true + @namevar = :name + @comment = /^#|^\s/ + @recordsep = "\n" end - return @childtype - end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.childtype=(childtype) - @childtype = childtype - end - #--------------------------------------------------------------- + # If they've passed in values, then set them appropriately. + unless hash.empty? + hash.each { |param, val| + meth = param.to_s + "=" + if self.respond_to? meth + self.send(meth, val) + end + } + end - #--------------------------------------------------------------- - def FileType.regex - return @regex - end - #--------------------------------------------------------------- + # If they've provided a block, then yield to it + if block_given? + yield newklass + end - #--------------------------------------------------------------- - def FileType.linesplit=(linesplit) - @regex = %r{#{linesplit}} - @linesplit = linesplit + @subclasses << newklass + return newklass end - #--------------------------------------------------------------- - #--------------------------------------------------------------- - def FileType.linesplit - return @linesplit + # Return the defined regex or the recordsep converted to one. + def FileType.regex + unless defined? @regex + @regex = %r{#{recordsep}} + end + return @regex end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - #def [](name) - # return @childhash[name] - #end - #--------------------------------------------------------------- - - #--------------------------------------------------------------- - #def []=(name,value) - #end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # we don't really have a 'less-than/greater-than' sense here # so i'm sticking with 'equals' until those make sense def ==(other) unless self.children.length == other.children.length - debug("file has %s records instead of %s" % + Puppet.debug("file has %s records instead of %s" % [self.children.length, other.children.length]) return self.children.length == other.children.length end equal = true self.zip(other.children) { |schild,ochild| unless schild == ochild - debug("%s has changed in %s" % + Puppet.debug("%s has changed in %s" % [schild.name,self.name]) equal = false break @@ -153,9 +148,7 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator return equal end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # create a new record with a block def add(type,&block) obj = self.class.records[type].new(self,&block) @@ -165,15 +158,11 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator return obj end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def children return @childary end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # remove a record def delete(name) if @childhash.has_key?(name) @@ -185,17 +174,13 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator raise "No such entry %s" % name end end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def each @childary.each { |child| yield child } end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # create a new file def initialize(hash) # if we are the FileType object itself, we create a new type @@ -214,9 +199,7 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator @childhash = {} super end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # this is where we're pretty different from other objects # we can choose to either reparse the existing file and compare # the objects, or we can write our file out and do an @@ -227,15 +210,11 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator return self == tmp end - #--------------------------------------------------------------- - #--------------------------------------------------------------- #def name # return @file #end - #--------------------------------------------------------------- - #--------------------------------------------------------------- # read the whole file in and turn it into each of the appropriate # objects def retrieve @@ -284,32 +263,24 @@ class Puppet::Type::FileType < Puppet::Type::TypeGenerator end } end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def sync #unless self.insync? self.write #end end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def to_s return @childary.collect { |child| child.to_s - }.join(self.class.linesplit) + self.class.linesplit + }.join(self.class.recordsep) + self.class.recordsep end - #--------------------------------------------------------------- - #--------------------------------------------------------------- def write ::File.open(@file, "w") { |file| file.write(self.to_s) } end - #--------------------------------------------------------------- end -#--------------------------------------------------------------- # $Id$ |
