2

I have a set of config files that need to be deployed to multiple locations on each server, each with different content, however they all share the same location structure. I'm trying to reduce the amount of replication I have in my manifests by making a common class which can be used multiple times.

Here's a simplified example of the file structures:

/home/bob/config/files.cfg
/home/bob/config/settings.cfg

/home/sue/config/files.cfg
/home/sue/config/settings.cfg

/home/ann/config/files.cfg
/home/ann/config/settings.cfg

And here's the manifest I've written.

class config-generic {
    file { "/home/$name/config/files.cfg":
        owner =>    $name,
        group =>    $name,
        source =>   "puppet://puppet.domain.com/files/home/$name/config/files.cfg",
        mode =>     644,
    }
    file { "/home/$name/config/settings.cfg":
        owner =>    $name,
        group =>    $name,
        source =>   "puppet://puppet.domain.com/files/home/$name/config/settings.cfg",
        mode =>     644,
    }
}

On the first use of the class it works fine.

node "client1", "client2" {
    class {'config-generic':
        name  => 'bob',
    }
}

However when I come to use the class again it errors because the class is already defined.

(Error 400 on SERVER: Duplicate definition: Class[config-generic] is already defined)

node "client1", "client2" {

    class {'config-generic':
        name  => 'bob',
    }

    class {'config-generic':
        name  => 'sue',
    }
}

Question: I understand the problem - however what's a better way of reducing replication in my manifests? I'm trying to avoid having to define a 'file' entry for each user for each file.

1 Answer 1

4

What you need is not a class, but a definition, since you want to make several instances of them, something like:

define config-generic ($ensure=present) {
    file { "/home/$name/config/files.cfg":
        ensure  =>  $ensure,
        owner   =>  $name,
        group   =>  $name,
        source  =>  "puppet://puppet.domain.com/files/home/$name/config/files.cfg",
        mode    =>  '0644',
    }
    file { "/home/$name/config/settings.cfg":
        ensure  =>  $ensure,
        owner   =>  $name,
        group   =>  $name,
        source  =>  "puppet://puppet.domain.com/files/home/$name/config/settings.cfg",
        mode    =>  '0644',
    }
}

and call it with:

node "client1", "client2" {

    config-generic {
      'bob':;    
      'sue':;
    }
}

You might also want to use a template if there's only small differences, instead of duplicating the source files.

3
  • That looks good. I'll give it a try. I was worried it wasn't possible. I was considering templates too, but I the changes will group rapidly over time.
    – Coops
    Apr 4, 2012 at 12:29
  • Cheers - works great :-)
    – Coops
    Apr 4, 2012 at 12:56
  • 1
    Note that you can also pass the users as an array, like config-generic { ['bob', 'sue']: } or even with a variable containing the array.
    – raphink
    Apr 4, 2012 at 12:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .