Ask Your Question

How do you programmatically add a normal resource to a custom stage?

asked 2017-10-03 05:12:03 -0600

busymeister gravatar image

Only classes can set the 'stage' parameter. Nonetheless, I would like to add a normal resource (like File, for example) to a custom stage programmatically inside a custom provider.. My idea is to first create an empty dummy class and assign it to the custom stage. Then, I want to add the normal resources to the catalog in my provider with a dependency on the empty dummy class. In my manifests I have

class { 'dummy':
    stage => 'custom'

and in my provider in the save function I have

message = Puppet::Type.newtype(:notify).new({
    title => @resource[:name],
    message => "i love #{@resource[:name]}"
dummy = catalog.resource('Class[dummy]')
catalog.add_resource_before(dummy, message)

But obviously, this does not work (otherwise, I wouldn't be asking the question :) ). How do I make something like this work?

edit retag flag offensive close merge delete


You can't. Your provider acts with a given resource declaration in a certain stage. You can't escape that stage. It's already sticking to you, with every line of code, like an attribute you can't lose. You'd had to step in at some point earlier, eventually tampering Puppet's source code.

Kai Burghardt gravatar imageKai Burghardt ( 2017-10-16 18:48:41 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted

answered 2017-10-21 06:33:25 -0600

busymeister gravatar image

updated 2017-10-21 06:36:13 -0600

After considerable experimentation, my conclusion is that any updates to the resource graph in the save/flush method of a custom provider are not processed by puppet; most likely, the graph is completely visited before the save/flush method is called and so any changes to it are at that point irrelevant.

Instead, I implemented the following method in my custom resource:

def generate
      message = Puppet::Type.type(:notify).new({
          :name      => self[:name],
          :message   => "i love #{self[:name]}"
      dummy = @catalog.resource('Class[dummy]')
      @catalog.add_resource_before(dummy, message)
      @catalog.add_edge(@catalog.container_of(dummy), message)

This method is called by puppet during catalog processing and is supposed to return extra resources that are to be added to the catalog. See the puppet source code. For an example of where generate/eval_generate are used, see the puppetlabs/concat module. Unfortunately, I do not understand what the difference is between generate and eval_generate but the method above works. See my other question.

The dummy class is a placeholder in the custom stage. The method above then adds the notify resource to the graph and attaches it to the dummy class. When I apply the catalog, the message is displayed when the custom stage runs.

Obviously, this is a bit of a hack. Ideally, the AdditionalResourceGenerator would accept an option for specifying the parent resource; in the current implementation, the parent resource is assumed to be the resource on which generate is called.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2017-10-03 05:11:36 -0600

Seen: 535 times

Last updated: Oct 21 '17