summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-10-01 21:03:42 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-10-01 21:03:42 +0000
commit6af0e0e5959e7b405191e0a916be097454a656e4 (patch)
tree886fc7cdebf9c7955aff6467302ec701012e792d
parent0d6241ca97ded8e003338c6cf316e280530ea8ee (diff)
downloadpuppet-6af0e0e5959e7b405191e0a916be097454a656e4.tar.gz
puppet-6af0e0e5959e7b405191e0a916be097454a656e4.tar.xz
puppet-6af0e0e5959e7b405191e0a916be097454a656e4.zip
added overrides ability
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@711 980ebf18-57e1-0310-9a29-db15c13687c0
-rw-r--r--lib/puppet/type.rb98
-rw-r--r--lib/puppet/type/pfile.rb40
-rwxr-xr-xtest/other/tc_overrides.rb114
3 files changed, 198 insertions, 54 deletions
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index 421cdf6ca..e0c31777b 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -435,20 +435,6 @@ class Type < Puppet::Element
end
end
- # remove a state from the object; useful in testing or in cleanup
- # when an error has been encountered
- def destroy
- self.class.delete(self)
-
- Puppet::Event::Subscription.dependencies(self).each { |dep|
- self.unsubscribe(dep)
- }
-
- if defined? @parent and @parent
- @parent.delete(self)
- end
- end
-
# iterate across all children, and then iterate across states
# we do children first so we're sure that all dependent objects
# are checked first
@@ -577,6 +563,25 @@ class Type < Puppet::Element
}
end
+ # Remove an object. The argument determines whether the object's
+ # subscriptions get eliminated, too.
+ def remove(rmdeps)
+ @children.each { |child|
+ child.remove
+ }
+ self.class.delete(self)
+
+ if rmdeps
+ Puppet::Event::Subscription.dependencies(self).each { |dep|
+ self.unsubscribe(dep)
+ }
+ end
+
+ if defined? @parent and @parent
+ @parent.delete(self)
+ end
+ end
+
# return an actual type by name; to return the value, use 'inst[name]'
# FIXME this method should go away
def state(name)
@@ -618,40 +623,51 @@ class Type < Puppet::Element
hash.delete(:implicit)
end
- if name = hash["name"] || hash[:name] ||
+ name = nil
+ unless name = hash["name"] || hash[:name] ||
hash[self.namevar] || hash[self.namevar.to_s]
- # if the object already exists
- if retobj = self[name]
- # if only one of our objects is implicit, then it's easy to see
- # who wins -- the non-implicit one.
+ raise Puppet::Error, "You must specify a name for objects of type %s" %
+ self.to_s
+ end
+ # if the object already exists
+ if retobj = self[name]
+ # if only one of our objects is implicit, then it's easy to see
+ # who wins -- the non-implicit one.
+ if retobj.implicit? and ! implicit
+ Puppet.warning "Removing implicit %s" % retobj.name
+ # Remove all of the objects, but do not remove their subscriptions.
+ retobj.remove(false)
+
+ # now pass through and create the new object
+ elsif implicit
+ Puppet.warning "Ignoring implicit %s" % name
+
+ return retobj
+ else
# merge the new data
retobj.merge(hash)
return retobj
- else
- # create it anew
- # if there's a failure, destroy the object if it got that far
- begin
- obj = new(hash)
- rescue => detail
- if Puppet[:debug]
- if detail.respond_to?(:stack)
- puts detail.stack
- end
- end
- Puppet.err "Could not create %s: %s" % [name, detail.to_s]
- if obj
- Puppet.err obj
- obj.destroy
- elsif obj = self[name]
- obj.destroy
- end
- return nil
+ end
+ end
+
+ # create it anew
+ # if there's a failure, destroy the object if it got that far
+ begin
+ obj = new(hash)
+ rescue => detail
+ if Puppet[:debug]
+ if detail.respond_to?(:stack)
+ puts detail.stack
end
end
- else
- raise Puppet::Error, "You must specify a name for objects of type %s" %
- self.to_s
+ Puppet.err "Could not create %s: %s" % [name, detail.to_s]
+ if obj
+ obj.remove(true)
+ elsif obj = self[name]
+ obj.remove(true)
+ end
+ return nil
end
end
diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb
index 82581998a..858b1995d 100644
--- a/lib/puppet/type/pfile.rb
+++ b/lib/puppet/type/pfile.rb
@@ -1165,24 +1165,38 @@ module Puppet
else
klass = self.class
end
+
+ # We know we're creating an implicit child. If the child we're
+ # trying to create already exists, then we know it should still
+ # be there, since if it shouldn't be, it would have already been
+ # removed. Either it's entirely explicit, in which case it
+ # should win, or it's implicit but resulting from a more explicit
+ # child.
if child = klass[path]
- unless @children.include?(child)
- raise Puppet::Error,
- "Planned child file %s of %s already exists with parent %s" %
- [path, self.name, child.parent]
- end
- args.each { |var,value|
- next if var == :path
- next if var == :name
- # behave idempotently
- unless child.should(var) == value
- child[var] = value
- end
- }
+ Puppet.warning "Not managing more explicit %s" % child
+ return nil
+ #unless @children.include?(child)
+ # raise Puppet::Error,
+ # "Planned child file %s of %s already exists with parent %s" %
+ # [path, self.name, child.parent]
+ #end
+ #args.each { |var,value|
+ # next if var == :path
+ # next if var == :name
+ # # behave idempotently
+ # unless child.should(var) == value
+ # child[var] = value
+ # end
+ #}
else # create it anew
#notice "Creating new file with args %s" % args.inspect
begin
child = klass.implicitcreate(args)
+
+ # implicit creation can return nil
+ if child.nil?
+ return nil
+ end
child.parent = self
@children << child
rescue Puppet::Error => detail
diff --git a/test/other/tc_overrides.rb b/test/other/tc_overrides.rb
new file mode 100755
index 000000000..6c7f91ddf
--- /dev/null
+++ b/test/other/tc_overrides.rb
@@ -0,0 +1,114 @@
+if __FILE__ == $0
+ $:.unshift '..'
+ $:.unshift '../../lib'
+ $puppetbase = "../.."
+end
+
+require 'puppet'
+require 'puppettest'
+require 'test/unit'
+
+class TestOverrides < TestPuppet
+ def mksubdirs(basedir, level)
+ @@tmpfiles << basedir
+ dir = basedir.dup
+
+ (level + 1).times { |index|
+ Dir.mkdir(dir)
+ path = File.join(dir, "file")
+ File.open(path, "w") { |f| f.puts "yayness" }
+ dir = File.join(dir, index.to_s)
+ }
+ end
+
+ def test_simpleoverride
+ basedir = File.join(tmpdir(), "overridetesting")
+ mksubdirs(basedir, 1)
+
+ baseobj = nil
+ basefile = File.join(basedir, "file")
+ assert_nothing_raised("Could not create base obj") {
+ baseobj = Puppet::Type::PFile.create(
+ :path => basedir,
+ :recurse => true,
+ :mode => "755"
+ )
+ }
+
+ subobj = nil
+ subdir = File.join(basedir, "0")
+ subfile = File.join(subdir, "file")
+ assert_nothing_raised("Could not create sub obj") {
+ subobj = Puppet::Type::PFile.create(
+ :path => subdir,
+ :recurse => true,
+ :mode => "644"
+ )
+ }
+
+ comp = newcomp("overrides", baseobj, subobj)
+ assert_nothing_raised("Could not eval component") {
+ trans = comp.evaluate
+ trans.evaluate
+ }
+
+ assert(File.stat(basefile).mode & 007777 == 0755)
+ assert(File.stat(subfile).mode & 007777 == 0644)
+ end
+
+ def test_zdeepoverride
+ basedir = File.join(tmpdir(), "deepoverridetesting")
+ mksubdirs(basedir, 10)
+
+ baseobj = nil
+ assert_nothing_raised("Could not create base obj") {
+ baseobj = Puppet::Type::PFile.create(
+ :path => basedir,
+ :recurse => true,
+ :mode => "755"
+ )
+ }
+
+ children = []
+ files = {}
+ subdir = basedir.dup
+ mode = nil
+ 10.times { |index|
+ next unless index % 3
+ subdir = File.join(subdir, index.to_s)
+ path = File.join(subdir, "file")
+ if index % 2
+ mode = "644"
+ files[path] = 0644
+ else
+ mode = "750"
+ files[path] = 0750
+ end
+
+ assert_nothing_raised("Could not create sub obj") {
+ children << Puppet::Type::PFile.create(
+ :path => subdir,
+ :recurse => true,
+ :mode => mode
+ )
+ }
+ }
+
+ comp = newcomp("overrides", baseobj)
+ children.each { |child| comp.push child }
+
+ assert_nothing_raised("Could not eval component") {
+ trans = comp.evaluate
+ trans.evaluate
+ }
+
+ files.each { |path, mode|
+ assert(FileTest.exists?(path), "File %s does not exist" % path)
+ curmode = File.stat(path).mode & 007777
+ assert(curmode == mode,
+ "File %s was incorrect mode %o instead of %o" % [path, curmode, mode])
+ }
+ end
+end
+
+# $Id$