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.

  • 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 '14 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 '14 at 14:32
  • If you are using include myclass this should be idempotent. If you are using class { "myclass" : } then you need to consider using hiera. Moreover, you can even consider virtual resources, another user here has suggested. – Felipe Alvarez Dec 8 '16 at 7:01

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.

  • 3
    ensure_resource is actually considered harmful. See e.g. groups.google.com/forum/… – Felix Frank May 5 '14 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 '14 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



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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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