After thinking about it for a bit, I thought I'd take a crack at
adding upwards recursion to the file type (Ticket #86). It seemed to
me that this would be relatively easy. Upwards recursion is *much*
simpler than downwards recursion in this case; everything upwards of
the resource is always going to be  simple file resource. We might
want to propagate permissions and ownership in some way, but I haven't
gotten that far yet. I'm not sure what I'm not understanding about how
this should work, so I thought I'd hit up the list for some advice.

I decided that since this was simpler than downwards recursion, and we
might want to do both, to add a parameter called :makeparents. Adding
the parameter was easy, and works as expected. Implementing the
behavior behind the parameter is giving me some trouble. Here's what I
have so far (in Ruby-like pseudocode with 'comments' that explain my
thought process):

# This is called from eval_generate(), like recurse().
def makeparents
    # First I want to generate a list of the parent directories.
    # I don't want the path of the resource I'm defining in this list,
    # so I start one level up the tree
    path = File.dirname(self[:path])
    stack = []
    until path == stack.last do
        stack.push(path)
        path = File.dirname(path)
    end

    # Make local copy of arguments so I can apply them to created
    # parent resources.
    args = symbolize_options(@arghash)

    # Parents are made in one pass, so we don't want the
    # created resources to try to make their own parents.
    args.delete(:makeparents)

    # Parents will, be definition, always be directories. On second thought,
    # they might be symlinks, but, again, I haven't gotten that far yet.
    args[:ensure] = :directory

    # Now for all of the parent paths we want to generate new
    # resources. I start at the top (stack.reverse_each) so that it is
    # easy to hook each resource to its parent.
    parent = nil
    stack.reverse_each do |path|
        # This is to avoid setting :parent for /
        args[:parent] = parent unless parent.nil?
        args[:path] = path

        # If there is already a resource in the catalog for this
        # directory, we should just use it.
        if current = catalog.resource(:file, path)
            # pseudocode: I can't figure out how to use an existing
            # resource. When I was trying tests, adding a file
            # resource for something somewhere up the tree caused my
            # code to not even be run anymore.
            somehow.use(current)
        else
            # Ignoring the debug lines, I thought this would be how I
            # generated the new resource.
            notice "Creating new file with args %s" % args.inspect
            current = catalog.create_implicit_resource(self.class.name, args)
            puts "created %s" % current["path"]
        end
        parent = current
    end
end

Here are some things that are puzzling me:
1) Is it enough to just create resources and return them to
eval_generate()? Will Puppet then know to apply them?
2) Am I working too hard to get :parent set? Does Puppet know enough
about directory structures to figure that out?
3) Here is my "test" (not the actual unit tests I am writing, just an
exploratory programming thing) that I am using to figure this out:

describe "when creating parent resources" do
    include PuppetTest
    require 'tempfile'

    before do
        @basedir = tempfile
        @path = File.join(@basedir, "foo/bar/baz")
        @resource = Puppet.type(:file).create(:path => @path, :ensure
=> :present, :content => "foo", :makeparents => true)
    after do
        remove_tmp_files
    end

    it "should help me understand Puppet internals" do
        @catalog.add_resource @resource
        # These are commented out because when I add them, the
        # :makeparents parameter of @resource is completely ignored
#         resource = Puppet.type(:file).create(:path =>
File.dirname(@path), :ensure => :directory)
#         @catalog.add_resource resource
        @catalog.apply
    end
# Actual unit tests that are all pending snipped because I'm just
trying to figure out how this works at this point.
end

3 [cont.]) Is this enough to supposedly create the resource and apply
it? If I add FileTest.exists?(@path).should be_true() at the end, it
fails. What am I missing?
4) How is eval_generate supposed to be used?

Any pointers, answers, or even RTFMs appreciated.

--Paul

--~--~---------~--~----~------------~-------~--~----~
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