The File type will now autorequire the nearest ancestor directory found in the
catalog, not just the file's parent directory. This is useful for setting up
transitive relationships in cases when a package or other resource creates a
large directory hierarchy, e.g.

  package { 'foo': ensure => present }
  file { '/var/lib/foo': require => Package['foo'] }

This will make File resources at arbitrarily deep levels under /var/lib/foo
automatically (transitively) require the foo package.

Only the nearest ancestor is autorequired, to prevent explosion of the
relationship graph.

Signed-off-by: Ian Ward Comfort <[email protected]>
---

On 18 Feb 2011, at 2:20 PM, Luke Kanies wrote:
> autorequire is a bit of a weird beast, so I know why you're having problems.
> 
> My code was just about changing the behavior of existing autorequire, rather
> than adding a new kind of autorequire.
> 
> The code I sent was just replacing the *call* to that method you're looking
> at - weird, but true.
> 
> Glad to hear it seems to work.  And I notice that your code is far simpler
> and clearer than mine. :)

OK, I was definitely quite confused before, but having spent some time
*actually* learning Ruby and swimming about this part of the codebase, I think
I've got it. Given the late stage at which Type#autorequire gets called, this
strategy works just fine.

This patch is based on master, but I can rebase if that's wrong. It can also
be pulled from:

  git://github.com/icomfort/puppet.git file-autorequire-first-ancestor

 lib/puppet/type/file.rb     |   10 ++++++++--
 spec/unit/type/file_spec.rb |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 963b9e5..da09392 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -244,11 +244,17 @@ Puppet::Type.newtype(:file) do
     newvalues(:first, :all)
   end
 
-  # Autorequire any parent directories.
+  # Autorequire the nearest ancestor directory found in the catalog.
   autorequire(:file) do
     basedir = File.dirname(self[:path])
     if basedir != self[:path]
-      basedir
+      parents = []
+      until basedir == parents.last
+        parents << basedir
+        basedir = File.dirname(basedir)
+      end
+      # The filename of the first ancestor found, or nil
+      parents.find { |dir| catalog.resource(:file, dir) }
     else
       nil
     end
diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb
index 539782f..cbd6812 100755
--- a/spec/unit/type/file_spec.rb
+++ b/spec/unit/type/file_spec.rb
@@ -169,6 +169,19 @@ describe Puppet::Type.type(:file) do
         reqs[0].target.must == file
       end
 
+      it "should autorequire its nearest ancestor directory" do
+        file = Puppet::Type::File.new(:path => "/foo/bar/baz")
+        dir = Puppet::Type::File.new(:path => "/foo")
+        root = Puppet::Type::File.new(:path => "/")
+        @catalog.add_resource file
+        @catalog.add_resource dir
+        @catalog.add_resource root
+        reqs = file.autorequire
+        reqs.length.must == 1
+        reqs[0].source.must == dir
+        reqs[0].target.must == file
+      end
+
       it "should not autorequire its parent dir if its parent dir is itself" do
         file = Puppet::Type::File.new(:path => "/")
         @catalog.add_resource file
@@ -242,6 +255,19 @@ describe Puppet::Type.type(:file) do
         reqs[0].target.must == file
       end
 
+      it "should autorequire its nearest ancestor directory" do
+        file = Puppet::Type::File.new(:path => "X:/foo/bar/baz")
+        dir = Puppet::Type::File.new(:path => "X:/foo")
+        root = Puppet::Type::File.new(:path => "X:/")
+        @catalog.add_resource file
+        @catalog.add_resource dir
+        @catalog.add_resource root
+        reqs = file.autorequire
+        reqs.length.must == 1
+        reqs[0].source.must == dir
+        reqs[0].target.must == file
+      end
+
       it "should not autorequire its parent dir if its parent dir is itself" do
         file = Puppet::Type::File.new(:path => "X:/")
         @catalog.add_resource file
@@ -303,6 +329,19 @@ describe Puppet::Type.type(:file) do
         reqs[0].target.must == file
       end
 
+      it "should autorequire its nearest ancestor directory" do
+        file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/qux")
+        dir = Puppet::Type::File.new(:path => "//server/foo/bar")
+        root = Puppet::Type::File.new(:path => "//server/foo")
+        @catalog.add_resource file
+        @catalog.add_resource dir
+        @catalog.add_resource root
+        reqs = file.autorequire
+        reqs.length.must == 1
+        reqs[0].source.must == dir
+        reqs[0].target.must == file
+      end
+
       it "should not autorequire its parent dir if its parent dir is itself" do
         file = Puppet::Type::File.new(:path => "//server/foo")
         @catalog.add_resource file
-- 
1.7.3.2

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to