summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/puppet/filetype.rb6
-rw-r--r--lib/puppet/parameter.rb12
-rw-r--r--lib/puppet/type.rb27
-rwxr-xr-xlib/puppet/type/cron.rb33
-rwxr-xr-xlib/puppet/type/parsedtype.rb143
-rwxr-xr-xlib/puppet/type/parsedtype/host.rb15
-rwxr-xr-xlib/puppet/type/parsedtype/port.rb80
-rwxr-xr-xlib/puppet/type/parsedtype/sshkey.rb10
-rw-r--r--lib/puppet/type/state.rb97
9 files changed, 218 insertions, 205 deletions
diff --git a/lib/puppet/filetype.rb b/lib/puppet/filetype.rb
index f67382b56..6525204ab 100755
--- a/lib/puppet/filetype.rb
+++ b/lib/puppet/filetype.rb
@@ -40,7 +40,11 @@ module Puppet
begin
val = real_read()
@loaded = Time.now
- return val.gsub(/# HEADER.*\n/,'')
+ if val
+ return val.gsub(/# HEADER.*\n/,'')
+ else
+ return ""
+ end
rescue Puppet::Error => detail
raise
rescue => detail
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index 82fa1bb0f..a3a935b00 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -290,7 +290,17 @@ module Puppet
# it possible to call for states, too.
def value
if self.is_a?(Puppet::State)
- return self.should
+ # We should return the 'is' value if there's not 'should' value.
+ # This might be bad, though, because the 'should' method
+ # knows whether to return an array or not and that info is
+ # not exposed, and the 'is' value could be a symbol. I can't
+ # seem to create a test in which this is a problem, but that doesn't
+ # mean it's not one.
+ if self.should
+ return self.should
+ else
+ return self.is
+ end
else
if defined? @value
return @value
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index cb05cb847..0c0fc2d98 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -1658,23 +1658,9 @@ class Type < Puppet::Element
@evalcount = 0
end
@@retrieved[self] += 1
- # if we're a metaclass and we've already evaluated once...
- #if self.metaclass and @evalcount > 0
- # return
- #end
@evalcount += 1
- #changes = @children.collect { |child|
- # child.evaluate
- #}
-
changes = []
- # collect all of the changes from children and states
- #if self.class.depthfirst?
- # changes << self.collect { |child|
- # child.evaluate
- # }
- #end
# this only operates on states, not states + children
# it's important that we call retrieve() on the type instance,
@@ -1698,16 +1684,6 @@ class Type < Puppet::Element
child.cache(:checked, now)
ch
}
- #unless self.class.depthfirst?
- # changes << self.collect { |child|
- # child.evaluate
- # }
- #end
- # collect changes and return them
- # these changes could be from child objects or from contained states
- #self.collect { |child|
- # child.evaluate
- #}
if self.class.depthfirst?
changes += statechanges()
@@ -1720,9 +1696,6 @@ class Type < Puppet::Element
if changes.length > 0
self.info "%s change(s)" %
[changes.length]
- #changes.each { |change|
- # self.debug "change: %s" % change.state.name
- #}
end
self.cache(:checked, now)
return changes.flatten
diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb
index 7e44125a2..978901a98 100755
--- a/lib/puppet/type/cron.rb
+++ b/lib/puppet/type/cron.rb
@@ -103,6 +103,11 @@ module Puppet
# a boolean of whether to do alpha checking, and if so requires
# the ary against which to do the checking.
munge do |value|
+ # Support 'absent' as a value, so that they can remove
+ # a value
+ if value == "absent" or value == :absent
+ return :absent
+ end
return value unless self.class.boundaries
lower, upper = self.class.boundaries
retval = nil
@@ -135,7 +140,10 @@ module Puppet
provided to the command varies by local system rules, and it is
best to always provide a fully qualified command. The user's
profile is not sourced when the command is run, so if the
- user's environment is desired it should be sourced manually."
+ user's environment is desired it should be sourced manually.
+
+ All cron parameters support ``absent`` as a value; this will
+ remove any existing values for that field."
end
newstate(:minute, CronParam) do
@@ -178,12 +186,13 @@ module Puppet
newparam(:name) do
desc "The symbolic name of the cron job. This name
- is used for human reference only and is generated
- automatically for cron jobs found on the system. This generally
- won't matter, as Puppet will do its best to match existing
- cron jobs against specified jobs (and Puppet adds a tag to
- cron jobs it adds), but it is at least possible that converting
- from unmanaged jobs to managed jobs might require manual intervention."
+ is used for human reference only and is generated automatically
+ for cron jobs found on the system. This generally won't
+ matter, as Puppet will do its best to match existing cron jobs
+ against specified jobs (and Puppet adds a tag to cron jobs it
+ adds), but it is at least possible that converting from
+ unmanaged jobs to managed jobs might require manual
+ intervention."
isnamevar
end
@@ -487,7 +496,9 @@ module Puppet
def exists?
val = false
- if @states.include?(:command) and @states[:command].is != :absent
+ if @states.include?(:command) and
+ @states[:command].is != :absent and
+ ! @states[:command].is.nil?
val = true
end
return val
@@ -523,7 +534,11 @@ module Puppet
return "# Puppet Name: %s\n" % self.name +
self.class.fields.collect { |f|
- hash[f] || "*"
+ if hash[f] and hash[f] != :absent
+ hash[f]
+ else
+ "*"
+ end
}.join(" ")
end
end
diff --git a/lib/puppet/type/parsedtype.rb b/lib/puppet/type/parsedtype.rb
index 2048ba934..0429bcdd1 100755
--- a/lib/puppet/type/parsedtype.rb
+++ b/lib/puppet/type/parsedtype.rb
@@ -9,6 +9,31 @@ module Puppet
# the 'should' value to the 'is' value and to do support the right logging
# and such.
class ParsedParam < Puppet::State
+ def self.isoptional
+ @isoptional = true
+ end
+
+ def self.isoptional?
+ if defined? @isoptional
+ return @isoptional
+ else
+ return false
+ end
+ end
+
+ # By default, support ':absent' as a value for optional
+ # parameters. Any parameters that define their own validation
+ # need to do this manuallly.
+ validate do |value|
+ if self.class.isoptional? and (
+ value == "absent" or value == :absent
+ )
+ return :absent
+ else
+ return value
+ end
+ end
+
# Fix things so that the fields have to match exactly, instead
# of only kinda
def insync?
@@ -32,40 +57,39 @@ module Puppet
end
end
- # Determine whether the host entry should be destroyed, and figure
- # out which event to return. Finally, call @parent.sync to write the
- # host tab.
+ # If the ensure state is out of sync, it will always be called
+ # first, so I don't need to worry about that.
def sync(nostore = false)
ebase = @parent.class.name.to_s
- if @is == :absent
- #@is = self.should
- tail = "created"
-
- # If we're creating it, then sync all of the other states
- # but tell them not to store (we'll store just once,
- # at the end).
- unless nostore
- @parent.eachstate { |state|
- next if state == self or state.name == :ensure
- state.sync(true)
- }
+
+ tail = nil
+ if self.class.name == :ensure
+ # We're either creating or destroying the object
+ if @is == :absent
+ #@is = self.should
+ tail = "created"
+
+ # If we're creating it, then sync all of the other states
+ # but tell them not to store (we'll store just once,
+ # at the end).
+ unless nostore
+ @parent.eachstate { |state|
+ next if state == self or state.name == :ensure
+ state.sync(true)
+ }
+ end
+ elsif self.should == :absent
+ @parent.remove(true)
+ tail = "deleted"
end
- elsif self.should == :absent
- @parent.remove(true)
- tail = "deleted"
- #elsif @is == @should
- elsif self.insync?
- self.info "Already in sync: %s vs %s" %
- [@is.inspect, @should.inspect]
- return nil
else
- #@is = self.should
- # Mark that we've synced it, but don't copy the value, because
- # that will make the 'change' log inscrutable.
+ # We don't do the work here, it gets done in 'store'
tail = "changed"
end
@synced = self.should
+ # This should really only be done once per run, rather than
+ # every time. I guess we need some kind of 'flush' mechanism.
if nostore
self.retrieve
else
@@ -106,7 +130,7 @@ module Puppet
super
end
- # In addition to removing the instances in @objects, Cron has to remove
+ # In addition to removing the instances in @objects, we have to remove
# per-user host tab information.
def self.clear
@instances = []
@@ -126,8 +150,9 @@ module Puppet
# Return the header placed at the top of each generated file, warning
# users that modifying this file manually is probably a bad idea.
def self.header
-%{# HEADER: This file was autogenerated at #{Time.now} by puppet. While it
-# HEADER: can still be managed manually, it is definitely not recommended.\n}
+%{# HEADER: This file was autogenerated at #{Time.now}
+# HEADER: by puppet. While it can still be managed manually, it
+# HEADER: is definitely not recommended.\n}
end
# Store a new instance of a host. Called from Host#initialize.
@@ -160,20 +185,30 @@ module Puppet
# we've set up our naming stuff correctly everywhere.
# Mark found objects as present
- Puppet.debug "Found %s %s" % [self.name, obj.name]
obj.is = [:ensure, :present]
+ hash.each { |param, value|
+ if state = obj.state(param)
+ state.is = value
+ elsif val = obj[param]
+ obj[param] = val
+ else
+ # There is a value on disk, but it should go away
+ obj.is = [param, value]
+ obj[param] = :absent
+ end
+ }
else
# create a new obj, since no existing one seems to
# match
- obj = self.create(
- :name => hash[:name]
- ) or return false
+ obj = self.create(:name => hash[:name])
+
+ # We can't just pass the hash in at object creation time,
+ # because it sets the should value, not the is value.
hash.delete(:name)
+ hash.each { |param, value|
+ obj.is = [param, value]
+ }
end
-
- hash.each { |param, value|
- obj.is = [param, value]
- }
end
# Retrieve the text for the file. Returns nil in the unlikely
@@ -205,14 +240,6 @@ module Puppet
else
@fileobj.write(self.to_file())
end
-
- #self.each { |obj|
- # obj.each { |state|
- # obj.notice "Changing from %s to %s" %
- # [state.is.inspect, state.should.inspect]
- # state.is = state.should
- # }
- #}
end
# Collect all Host instances convert them into literal text.
@@ -223,9 +250,6 @@ module Puppet
# Don't write out objects that should be absent
if obj.is_a?(self)
if obj.should(:ensure) == :absent
- #obj.warning "removing; is = %s, should = %s" %
- # [obj.is(:ensure).inspect, obj.should(:ensure).inspect]
- #obj.is = [:ensure, :absent]
true
end
end
@@ -239,7 +263,7 @@ module Puppet
return str
else
- Puppet.notice "No host instances"
+ Puppet.notice "No %s instances" % self.name
return ""
end
end
@@ -262,7 +286,8 @@ module Puppet
state.is_a?(Puppet::State::ParsedParam)
}
- if state.is == :absent
+ # Unless we've retrieved, we don't know if we exist
+ if ! state.is or state.is == :absent
return false
else
return true
@@ -286,6 +311,24 @@ module Puppet
def store
self.class.store()
end
+
+ def value(name)
+ unless name.is_a? Symbol
+ name = name.intern
+ end
+ if @states.include? name
+ val = @states[name].value
+ if val == :absent
+ return nil
+ else
+ return val
+ end
+ elsif @parameters.include? name
+ return @parameters[name].value
+ else
+ return nil
+ end
+ end
end
end
end
diff --git a/lib/puppet/type/parsedtype/host.rb b/lib/puppet/type/parsedtype/host.rb
index e70f2dfc1..6463232c1 100755
--- a/lib/puppet/type/parsedtype/host.rb
+++ b/lib/puppet/type/parsedtype/host.rb
@@ -5,6 +5,7 @@ require 'puppet/type/state'
module Puppet
newtype(:host, Puppet::Type::ParsedType) do
+
newstate(:ip) do
desc "The host's IP address."
end
@@ -73,12 +74,6 @@ module Puppet
@fields = [:ip, :name, :alias]
@filetype = Puppet::FileType.filetype(:flat)
-# case Facter["operatingsystem"].value
-# when "Solaris":
-# @filetype = Puppet::FileType::SunOS
-# else
-# @filetype = Puppet::CronType::Default
-# end
# Parse a host file
#
@@ -117,8 +112,6 @@ module Puppet
hash.delete(:alias)
end
- Puppet.notice "sending %s" % hash.inspect
-
hash2obj(hash)
hash.clear
@@ -129,10 +122,10 @@ module Puppet
# Convert the current object into a host-style string.
def to_record
- str = "%s\t%s" % [self.state(:ip).should, self[:name]]
+ str = "%s\t%s" % [self.state(:ip).value, self[:name]]
- if state = self.state(:alias)
- str += "\t%s" % state.should.join("\t")
+ if value = self.value(:alias)
+ str += "\t%s" % value.join("\t")
end
str
diff --git a/lib/puppet/type/parsedtype/port.rb b/lib/puppet/type/parsedtype/port.rb
index 52057d21c..369d2aea3 100755
--- a/lib/puppet/type/parsedtype/port.rb
+++ b/lib/puppet/type/parsedtype/port.rb
@@ -28,12 +28,22 @@ module Puppet
# We actually want to return the whole array here, not just the first
# value.
def should
- @should
+ if defined? @should
+ if @should[0] == :absent
+ return :absent
+ else
+ return @should
+ end
+ else
+ return nil
+ end
end
validate do |value|
- unless value == "udp" or value == "tcp"
- raise Puppet::Error, "Protocols can be either 'udp' or 'tcp'"
+ valids = ["udp", "tcp", "ddp", :absent]
+ unless valids.include? value
+ raise Puppet::Error,
+ "Protocols can be either 'udp' or 'tcp', not %s" % value
end
end
end
@@ -47,10 +57,10 @@ module Puppet
end
newstate(:alias) do
- desc "Any aliases the port might have. Multiple values must be specified
- as an array. Note that this state has the same name as one of the
- metaparams; using this state to set aliases will make those aliases
- available in your Puppet scripts and also on disk."
+ desc "Any aliases the port might have. Multiple values must be
+ specified as an array. Note that this state has the same name as
+ one of the metaparams; using this state to set aliases will make
+ those aliases available in your Puppet scripts and also on disk."
# We have to override the feeding mechanism; it might be nil or
# white-space separated
@@ -71,18 +81,32 @@ module Puppet
# We actually want to return the whole array here, not just the first
# value.
def should
- @should
+ if defined? @should
+ if @should[0] == :absent
+ return :absent
+ else
+ return @should
+ end
+ else
+ return nil
+ end
end
validate do |value|
- if value =~ /\s/
- raise Puppet::Error, "Aliases cannot have whitespace in them"
+ if value.is_a? String and value =~ /\s/
+ raise Puppet::Error,
+ "Aliases cannot have whitespace in them: %s" %
+ value.inspect
end
end
munge do |value|
- # Add the :alias metaparam in addition to the state
- @parent.newmetaparam(@parent.class.metaparamclass(:alias), value)
+ unless value == "absent" or value == :absent
+ # Add the :alias metaparam in addition to the state
+ @parent.newmetaparam(
+ @parent.class.metaparamclass(:alias), value
+ )
+ end
value
end
end
@@ -101,12 +125,6 @@ module Puppet
@fields = [:ip, :name, :alias]
@filetype = Puppet::FileType.filetype(:flat)
-# case Facter["operatingsystem"].value
-# when "Solaris":
-# @filetype = Puppet::FileType::SunOS
-# else
-# @filetype = Puppet::CronType::Default
-# end
# Parse a services file
#
@@ -122,10 +140,6 @@ module Puppet
# add comments and blank lines to the list as they are
@instances << line
else
- #if match = /^(\S+)\s+(\d+)\/(\w+)/.match(line)
- # Puppet.warning "%s %s %s" % [$1, $2, $3]
- # next
- #if line.sub(/^(\S+)\s+(\d+)\/(\w+)\s*(\S*)$/.match(line)
if line.sub!(/^(\S+)\s+(\d+)\/(\w+)\s*/, '')
hash[:name] = $1
hash[:number] = $2
@@ -134,6 +148,9 @@ module Puppet
unless line == ""
line.sub!(/^([^#]+)\s*/) do |value|
aliases = $1
+
+ # Remove any trailing whitespace
+ aliases.strip!
unless aliases =~ /^\s*$/
hash[:alias] = aliases
end
@@ -175,6 +192,9 @@ module Puppet
unless @states.include?(:protocols)
return false
end
+
+ # This method is only called from parsing, so we only worry
+ # about 'is' values.
proto = self.state(:protocols).is
if proto.nil? or proto == :absent
@@ -192,9 +212,7 @@ module Puppet
unless proto.include?(hash[:protocols])
# We are missing their proto
proto << hash[:protocols]
- #Puppet.info "new proto is %s" % proto.inspect
@states[:protocols].is = proto
- #Puppet.info "new value is %s" % @states[:protocols].is.inspect
end
end
@@ -206,20 +224,20 @@ module Puppet
return true
end
- # Convert the current object into a host-style string.
+ # Convert the current object into one or more services entry.
def to_record
- self.state(:protocols).should.collect { |proto|
- str = "%s\t%s/%s" % [self[:name], self.state(:number).should,
+ self.state(:protocols).value.collect { |proto|
+ str = "%s\t%s/%s" % [self[:name], self.value(:number),
proto]
- if state = self.state(:alias)
- str += "\t%s" % state.should.join(" ")
+ if value = self.value(:alias) and value != :absent
+ str += "\t%s" % value.join(" ")
else
str += "\t"
end
- if state = self.state(:description)
- str += "\t# %s" % state.should
+ if value = self.value(:description) and value != :absent
+ str += "\t# %s" % value
else
str += "\t"
end
diff --git a/lib/puppet/type/parsedtype/sshkey.rb b/lib/puppet/type/parsedtype/sshkey.rb
index 641741233..c1a09bb11 100755
--- a/lib/puppet/type/parsedtype/sshkey.rb
+++ b/lib/puppet/type/parsedtype/sshkey.rb
@@ -27,7 +27,11 @@ module Puppet
# We actually want to return the whole array here, not just the first
# value.
def should
- @should
+ if defined? @should
+ return @should
+ else
+ return nil
+ end
end
validate do |value|
@@ -119,9 +123,9 @@ module Puppet
def to_record
name = self[:name]
if @states.include?(:alias)
- name += "," + @states[:alias].should.join(",")
+ name += "," + @states[:alias].value.join(",")
end
- [name, @states[:type].should, @states[:key].should].join(" ")
+ [name, @states[:type].value, @states[:key].value].join(" ")
end
end
end
diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb
index 377e84a65..f090f38ec 100644
--- a/lib/puppet/type/state.rb
+++ b/lib/puppet/type/state.rb
@@ -39,42 +39,6 @@ class State < Puppet::Parameter
define_method("set_" + name.to_s, &block)
end
-#
-# def self.aliasvalue(name, other)
-# @statevalues ||= {}
-# unless @statevalues.include?(other)
-# raise Puppet::DevError, "Cannot alias nonexistent value %s" % other
-# end
-#
-# @aliasvalues ||= {}
-# @aliasvalues[name] = other
-# end
-#
-# def self.alias(name)
-# @aliasvalues[name]
-# end
-#
- def self.defaultvalues
- newvalue(:present) do
- @parent.create
- end
-
- newvalue(:absent) do
- @parent.destroy
- end
-
- # This doc will probably get overridden
- @doc ||= "The basic state that the object should be in."
- end
-#
-# # Return the list of valid values.
-# def self.values
-# @statevalues ||= {}
-# @aliasvalues ||= {}
-#
-# #[@aliasvalues.keys, @statevalues.keys].flatten
-# @statevalues.keys
-# end
# Call the method associated with a given value.
def set
@@ -278,46 +242,13 @@ class State < Puppet::Parameter
self.set
end
-# munge do |value|
-# if self.class.values.empty?
-# # This state isn't using defined values to do its work.
-# return value
-# end
-# intern = value.to_s.intern
-# # If it's a valid value, always return it as a symbol.
-# if self.class.values.include?(intern)
-# retval = intern
-# elsif other = self.class.alias(intern)
-# self.info "returning alias %s for %s" % [other, intern]
-# retval = other
-# else
-# retval = value
-# end
-# retval
-# end
-#
-# # Verify that the passed value is valid.
-# validate do |value|
-# if self.class.values.empty?
-# # This state isn't using defined values to do its work.
-# return
-# end
-# unless value.is_a?(Symbol)
-# value = value.to_s.intern
-# end
-# unless self.class.values.include?(value) or self.class.alias(value)
-# self.fail "Invalid '%s' value '%s'. Valid values are '%s'" %
-# [self.class.name, value, self.class.values.join(", ")]
-# end
-# end
-
# How should a state change be printed as a string?
def change_to_s
begin
if @is == :absent
return "defined '%s' as '%s'" %
[self.name, self.should_to_s]
- elsif self.should == :absent
+ elsif self.should == :absent or self.should == [:absent]
return "undefined %s from '%s'" %
[self.name, self.is_to_s]
else
@@ -341,7 +272,11 @@ class State < Puppet::Parameter
end
def should_to_s
- @should.join(" ")
+ if defined? @should
+ @should.join(" ")
+ else
+ return nil
+ end
end
def to_s
@@ -349,10 +284,23 @@ class State < Puppet::Parameter
end
# This state will get automatically added to any type that responds
- # to the methods 'exists?', 'create', and 'remove'.
+ # to the methods 'exists?', 'create', and 'destroy'.
class Ensure < Puppet::State
@name = :ensure
+ def self.defaultvalues
+ newvalue(:present) do
+ @parent.create
+ end
+
+ newvalue(:absent) do
+ @parent.destroy
+ end
+
+ # This doc will probably get overridden
+ @doc ||= "The basic state that the object should be in."
+ end
+
def self.inherited(sub)
# Add in the two states that everyone will have.
sub.class_eval do
@@ -378,6 +326,11 @@ class State < Puppet::Parameter
end
def retrieve
+ # XXX This is a problem -- whether the object exists or not often
+ # depends on the results of other states, yet we're the first state
+ # to get checked, which means that those other states do not have
+ # @is values set. This seems to be the source of quite a few bugs,
+ # although they're mostly logging bugs, not functional ones.
if @parent.exists?
@is = :present
else