summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-03 15:41:39 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-03 15:41:39 +0000
commite2e2fb3f2a771cca16e64cb027615e979fa8d586 (patch)
tree84ecca73bb12048d3cb914d03c1f4f0e74a484ae /lib
parent5302921b2e3698f864c2955a67dd9779c8aea18b (diff)
downloadpuppet-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.rb43
-rw-r--r--lib/puppet/type/typegen/filerecord.rb174
-rw-r--r--lib/puppet/type/typegen/filetype.rb227
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$