Classes & Defines in Puppet

puppet

Although I know the immediate solution to a problem I was facing yesterday (thanks to the folks over at IRC #puppet), I still don't understand how it solved the problem, or rather what's the fundamental difference between classes and defines in this particular scenario:

The original define, which was incorrect:

define srv($name,$enable="true",$ensure="running",$provider="runit",$hasstatus="true",$hasrestart="true"){

                exec {"sleep 5": path=>"/usr/bin:/usr/sbin:/bin:/sbin", before=>Service["$name"],}

                service{"$name":

                    enable=>$enable,
                    ensure=>$ensure,
                    provider=>$provider,
                    hasstatus=>$hasstatus,
                    hasrestart=>$hasrestart,
                } 
                              }

err: Could not retrieve catalog from
remote server: Error 400 on SERVER:
Duplicate definition: Exec[sleep 5] is
already defined in file
/etc/puppet/modules/common/manifests/defines/srv.pp
at line 4; cannot redefine at
/etc/puppet/modules/common/manifests/defines/srv.pp:4
on node testing.abc.def.com

The correct define:

define srv($enable="true",$ensure="running",$provider="runit",$hasstatus="true",$hasrestart="true"){

                exec {"sleep 5 for $name": command=>"sleep 5", path=>"/usr/bin:/usr/sbin:/bin:/sbin", before=>Service["$name"],}

                service{"$name":

                    enable=>$enable,
                    ensure=>$ensure,
                    provider=>$provider,
                    hasstatus=>$hasstatus,
                    hasrestart=>$hasrestart,
                }
                              }

So, why the error in the first case ? How am I duplicating a definition or in other words, if there was a single module using this define then would have the first define worked ? Maybe its the puppet terminology in the docs that has left me confused, but having written a ton of (working) modules and not understanding this sounds dangerous to me, hope I can get some clear answers.

Best Answer

Resources in Puppet have to be unique, i. e. have to have a unique name.

In the described case, you had the resource Exec["sleep 5"] in your definition and every time you call srv (it's basically the same as including a parameterized class), the resource Exec["sleep 5"] will also be included and thus the parser finds two or more resources with the same name.

By appending the $name of the definition to the name of your Exec resource, you make it unique. Well, at least most likely unique since when you have another resource with the same name (Exec["sleep 5 for foo") somewhere else in your manifests, you'll run into this error again.