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

share|improve this question

1 Answer 1

up vote 4 down vote accepted

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.

share|improve this answer
    
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 '12 at 12:29
    
Cheers - works great :-) –  Coops Apr 4 '12 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. –  ℝaphink Apr 4 '12 at 12:59

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.