Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a class which prepares config files and keys inside the puppet files folder so that they can be downloaded by other nodes. The class will be called once for every other node besides the puppet master.

The problem I have is that I only need to create the root directory once, e.g with:

file { '/etc/puppet/files/root':
  ensure => directory
}

However this results in a duplicate resource when I start calling the class multiple times.

I'm aware that I could fix it quite simply by using something like this to give a unique resource title:

file { "create-parent-dir-for-${name}":
  path => '/etc/puppet/files/rootdir',
  ensure => directory
}

But it feels wrong to create many additional resources to do the same thing, so I'm interested to find out if there is a alternative solution.

share|improve this question
    
Hello! Why do you create the resource several times if you need it only once? I don't know your whole code, but would consider putting the generic stuff like the creation of that folder in a separate class, then import the class where needed thenRequire the directory resource. –  Petter H May 4 at 10:49
    
I did try that way but the only way but it still complains about a duplicate declaration unless I add the include outside of the main class. –  Philio May 4 at 14:32

2 Answers 2

up vote 1 down vote accepted

I'm not completely sure if there isn't a nicer way to solve this (something like moving that common directory into a separate class which only gets called once).

But in any case, there is the stdlib function ensure_resource (https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resource) which does exactly this.
You would call it like this in both places:

ensure_resource('file', '/etc/puppet/files/root', {'ensure' => 'directory' })

Like I've said, there are usually better ways to resolve this.
It's hard to say if this is a good solution for you without seeing the full code.
Use with caution.

share|improve this answer
    
Haven't tried this so will give it a go, thanks! –  Philio May 4 at 13:03
    
This works nicely, thanks for your help! –  Philio May 4 at 14:47
    
ensure_resource is actually considered harmful. See e.g. groups.google.com/forum/… –  Felix Frank May 5 at 16:08
    
@FelixFrank it's controversial for sure. That's why I've wrote that there are usual better ways to solve this and that you should use it with caution. –  faker May 5 at 16:26

This is what virtual resources are for.

@file { "/etc/puppet/files/rootdir": ensure => directory }

Where it's needed, realize it either using

realize(File["/etc/puppet/files/rootdir"])

or

File<| title == "/etc/puppet/files/rootdir" |>

As an aside, classes will never yield duplicate declaration errors. You apparently declared the file inside a defined type. You can indeed work around this particular problem by doing it like Petter H suggested in his comment.

class files {
    file { "/etc/puppet/files/rootdir": ensure => directory }
}

define my_cool_type($param...) {
    include files
    ... # <- only stuff that is unique to this instance of my_cool_type
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.