Don
2009-Jun-17 03:26 UTC
[Puppet Users] Server Hierarchies and other configuration questions
I apologize if this has been asked before but if it has- my google technique has failed me. If anyone can point me at the right docs I''m happy to dive right in. While I''m not having any problems with Puppet, I am having some trouble understanding the best practices. Specifically: I have a basenode defined. I also have several different collections of servers and workstations. I''ve created a class called prodservers, a class called devservers and a class called workstations- each one inherits basenode and is then inherited by specific nodes. Should I be doing this in a class? If so what is the best place to store these class definitions- right now I am using manifests/classes/ workstation.pp and server.pp. Should this be done in a module instead? Putting specific configuration settings in a module (even if it is a module called "workstation" just feels wrong. http://reductivelabs.com/trac/puppet/wiki/PuppetBestPractice specifically says: "Stop using the manifests area to house classes, definitions, etc. Instead, use module exclusively to manage almost every single class, definition, template, file, etc." That would seem to run counter to the way I''ve done things. What am I missing? I''d like the admin that comes after me to be able to make sense of this deployment. Another question: The sample templates.pp in the best practices page defines a baseclass and then several types of servers. In what case would you define a baseclass instead of a basenode that you inherit? If you have different classes of servers then templates.pp can easily get unwieldy. I''m using templates.pp and just including my server and workstation specific classes. Is there a more sensible way to organize this? Lastly: Was there a technical reason to split out /services/ and /clients/ from the rest of the modules? It seems somewhat arbitrary and makes configuring certain services a little less intuitive (for example: NTP which is included on all servers, but has a different configuration on the NTP master). What''s the best practice here? Do people create a subclass that overrides and disables the generic NTP config and substitutes a server config? What''s the best way to define a "::disabled" class? The best practices gives openssh::disabled as an example but I''m having trouble understanding how that would work if the openssh class was already added to the generic server class, but needed to be disabled on a specific system. My apologies for the length of the email- I''ve been having a lot of fun writing recipes for puppet but these questions have been stopping me from going all out with my deployment. I''d like to get it right (or as close as possible) the first time. Thanks, -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
David Schmitt
2009-Jun-17 10:07 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
Don wrote:> I apologize if this has been asked before but if it has- my google > technique has failed me. If anyone can point me at the right docs I''m > happy to dive right in. > > While I''m not having any problems with Puppet, I am having some > trouble understanding the best practices. > > Specifically: > I have a basenode defined. I also have several different collections > of servers and workstations. I''ve created a class called prodservers, > a class called devservers and a class called workstations- each one > inherits basenode and is then inherited by specific nodes. Should I be > doing this in a class? If so what is the best place to store these > class definitions- right now I am using manifests/classes/ > workstation.pp and server.pp. Should this be done in a module instead? > Putting specific configuration settings in a module (even if it is a > module called "workstation" just feels wrong. > > http://reductivelabs.com/trac/puppet/wiki/PuppetBestPractice > specifically says: > "Stop using the manifests area to house classes, definitions, etc. > Instead, use module exclusively to manage almost every single class, > definition, template, file, etc." > > That would seem to run counter to the way I''ve done things. What am I > missing? I''d like the admin that comes after me to be able to make > sense of this deployment.I like to think about modules as "implementation", while the manifests area is "configuration" and "policy." That a node of the "webserver" kind should have an apache and a NTP client is policy and thus belongs into the manifest area. What in _means_ to have apache and NTP installed is implentation and should be defined in their respective modules.> Another question: > The sample templates.pp in the best practices page defines a baseclass > and then several types of servers. In what case would you define a > baseclass instead of a basenode that you inherit?> If you have different classes of servers then templates.pp can easily > get unwieldy. I''m using templates.pp and just including my server and > workstation specific classes. Is there a more sensible way to organize > this? > If you ever want to switch to external node classification, it is good to have nodes that look like this: node name { $var1 = val1 $var2 = val2 include class1, class2 }> Lastly: > Was there a technical reason to split out /services/ and /clients/ > from the rest of the modules? It seems somewhat arbitrary and makes > configuring certain services a little less intuitive (for example: NTP > which is included on all servers, but has a different configuration on > the NTP master).My own ntp module[1] only knows two kinds of ntp hosts: servers and clients. The former connect to each other and external sources, while the latter only connect to the local servers. The distinction is easily done: those nodes which have set $ntp_servers are those which connect to these external servers and thus _are_ servers. All others are clients. > What''s the best practice here? Do people create a> subclass that overrides and disables the generic NTP config and > substitutes a server config? What''s the best way to define a > "::disabled" class? The best practices gives openssh::disabled as an > example but I''m having trouble understanding how that would work if > the openssh class was already added to the generic server class, but > needed to be disabled on a specific system.You can include classes that inherit from classes that are already included and this will "patch up" the resources. The following is legal and will result in a disabled openssh service on the node "strange": class openssh { service { openssh: ensure => running, enable => true } class disabled inherits openssh { Service[openssh] { ensure => stopped, enable => false } } } node fine { include openssh } node strange inherits fine { include openssh::disabled } Regards, DavidS [1] http://git.black.co.at/?p=module-ntp --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Don
2009-Jun-17 13:47 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
> My own ntp module[1] only knows two kinds of ntp hosts: servers and > clients. The former connect to each other and external sources, while > the latter only connect to the local servers. The distinction is easily > done: those nodes which have set $ntp_servers are those which connect to > these external servers and thus _are_ servers. All others are clients.I did this too initially- but I consider NTP an "enterprise" service and was going to put it in /services/ but then I would end up with two NTP modules- one for NTP servers in /services and one for NTP clients. That seems really hackish.> You can include classes that inherit from classes that are already > included and this will "patch up" the resources. The following is legal > and will result in a disabled openssh service on the node "strange": > > class openssh { > service { openssh: ensure => running, enable => true } > class disabled inherits openssh { > Service[openssh] { ensure => stopped, enable => false } > } > } > > node fine { > include openssh > } > > node strange inherits fine { > include openssh::disabled > }I understand how this would work for a service like ssh- but what about in the case of something like NTP? In that case I would have: class ntp { file { "/etc/ntp.conf": source => "puppet:///ntp/ntpclient.conf", require => Package["ntp"] } } class s_ntp { # in /services file { "/etc/ntp.conf": source => "puppet:///s_ntp/ntpserver.conf", require => Package["ntp"] } } node basenode { include ntp } node xyz inherits basenode { } Now if I do this for my NTP master: node ntpmaster inherits basenode { include s_ntp } I''m going to have two NTP files. Is there a way to excude the earlier definition of NTP so I''m not trying to have it update the same file twice? Is there a more sensible way of doing this that I''m not thinking of? Should I just avoid /services because I clearly don''t understand what it''s for? -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
David Schmitt
2009-Jun-18 08:20 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
Don wrote:>> My own ntp module[1] only knows two kinds of ntp hosts: servers and >> clients. The former connect to each other and external sources, while >> the latter only connect to the local servers. The distinction is easily >> done: those nodes which have set $ntp_servers are those which connect to >> these external servers and thus _are_ servers. All others are clients. > I did this too initially- but I consider NTP an "enterprise" service > and was > going to put it in /services/ but then I would end up with two NTP > modules- > one for NTP servers in /services and one for NTP clients. That seems > really > hackish. > >> You can include classes that inherit from classes that are already >> included and this will "patch up" the resources. The following is legal >> and will result in a disabled openssh service on the node "strange": >> >> class openssh { >> service { openssh: ensure => running, enable => true } >> class disabled inherits openssh { >> Service[openssh] { ensure => stopped, enable => false } >> } >> } >> >> node fine { >> include openssh >> } >> >> node strange inherits fine { >> include openssh::disabled >> } > I understand how this would work for a service like ssh- but what > about in the case of something > like NTP? In that case I would have: > > class ntp { > file { "/etc/ntp.conf": > source => "puppet:///ntp/ntpclient.conf", > require => Package["ntp"] > } > } > > class s_ntp { # in /services > file { "/etc/ntp.conf": > source => "puppet:///s_ntp/ntpserver.conf", > require => Package["ntp"] > } > } > > node basenode { > include ntp > } > > node xyz inherits basenode { > } > > Now if I do this for my NTP master: > > node ntpmaster inherits basenode { > include s_ntp > } > > I''m going to have two NTP files. Is there a way to excude the earlier > definition of NTP so I''m not trying to have it update the same file > twice?No, you need to use inheritance.> Is there a more sensible way of doing this that I''m not thinking of? > > Should I just avoid /services because I clearly don''t understand what > it''s > for?I would say that everything concerning NTP should go into one module. Perhaps the PuppetBEstPractices document needs a bit refactoring there. Regards, DavidS --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Evan Hisey
2009-Jun-23 15:40 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
On Wed, Jun 17, 2009 at 8:47 AM, Don<don@blacksun.org> wrote:> >> My own ntp module[1] only knows two kinds of ntp hosts: servers and >> clients. The former connect to each other and external sources, while >> the latter only connect to the local servers. The distinction is easily >> done: those nodes which have set $ntp_servers are those which connect to >> these external servers and thus _are_ servers. All others are clients. > I did this too initially- but I consider NTP an "enterprise" service > and was > going to put it in /services/ but then I would end up with two NTP > modules- > one for NTP servers in /services and one for NTP clients. That seems > really > hackish. >> I understand how this would work for a service like ssh- but what > about in the case of something > like NTP? In that case I would have: > > class ntp { > file { "/etc/ntp.conf": > source => "puppet:///ntp/ntpclient.conf", > require => Package["ntp"] > } > } > > class s_ntp { # in /services > file { "/etc/ntp.conf": > source => "puppet:///s_ntp/ntpserver.conf", > require => Package["ntp"] > } > } > > node basenode { > include ntp > } > > node xyz inherits basenode { > } > > Now if I do this for my NTP master: > > node ntpmaster inherits basenode { > include s_ntp > } > > I''m going to have two NTP files. Is there a way to excude the earlier > definition of NTP so I''m not trying to have it update the same file > twice? > > Is there a more sensible way of doing this that I''m not thinking of? > > Should I just avoid /services because I clearly don''t understand what > it''s > for? >This were template files com in really handy. Instead of having two ntp .conf files you use one ntp_conf.erb that has a case switch. When $ntp_server is set to true then you get one config file out of the template, if it is false or not set you get a second. the template file could look something like this: # NTP file manged by Puppet, any local edits will be lost # <% if ntp_server == true -%> ~ insert server configuration ~ <% end -%> ~ insert the client configuration~ # # EOF This will make an ntp.conf file that always has the same client information, for connecting to local ntp servers. Only files that are defined as being $ntp_server == true will get the server configuration information. Now your ntp class might look like this: class ntp { file { "/etc/ntp.conf": source => template("ntp/ntp_conf.erb"), require => Package["ntp"], } } And your node definitions like this: ( the change from inherit to include is caused by variable scoping) node basenode { include ntp } node xyz inherits basenode { } NTP master: node ntpmaster{ $ntp_server=true include basenode } Evan --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Don
2009-Jun-23 17:43 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
> This were template files com in really handy. Instead of having two > ntp .conf files you use one ntp_conf.erb that has a case switch.If I put a case statement in the .erb file then I''ve tied the template to a specific host or set of hosts. I''d rather pass in the variables to the template and keep the logic outside the template. This is sort of what I''ve done. I end up with a template file that accepts things like the master servers as an array, as well as the ACL''s and so on. It populates just fine with the variables I specify. I specify a null set of ACL''s for the clients, and different masters and such for the servers. In the end we come back to the same sort of problem though- It''s not possible to override values, and so we define everything backwards. That, plus the scoping rules, makes it (to me at least) very difficult to build a nice clean organizational structure. -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Evan Hisey
2009-Jun-23 19:51 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
On Tue, Jun 23, 2009 at 12:43 PM, Don<don@blacksun.org> wrote:> >> This were template files com in really handy. Instead of having two >> ntp .conf files you use one ntp_conf.erb that has a case switch. > If I put a case statement in the .erb file then I''ve tied the template > to a specific host or set of hosts. I''d rather pass in the variables > to the template and keep the logic outside the template.Here I am seeing a thought process barrier. You do not have to tye a template case to _servers_ by name. The idea is to tye the template case to _roles_. That way it does not matter what the server name is or where it is. If it is defined as have having a ntp server role then it gets that configuration. One of the strengths I have found in templates is that you can but the logic in the template. Pass the roles you want the server to play to the template , server , client, or client and server and the template sorts itself out to produce the correct config file to hand out. Also remeber anything you can do in ruby you can pretty much do in the templates. You may also want to look at the generate function. It lets you call external scripts to produce results that will be used by puppet for things like source.> This is sort of what I''ve done. I end up with a template file that > accepts things like the master servers as an array, as well as the > ACL''s and so on. It populates just fine with the variables I specify. > I specify a null set of ACL''s for the clients, and different masters > and such for the servers.> In the end we come back to the same sort of problem though- It''s not > possible to override values, and so we define everything backwards. > That, plus the scoping rules, makes it (to me at least) very difficult > to build a nice clean organizational structure.evan --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Don
2009-Jun-23 21:37 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
> Here I am seeing a thought process barrier. You do not have to tye a > template case to _servers_ by name. The idea is to tye the template > case to _roles_.Great- I have a "role" called NTP master. The NTP master in datacenter A uses a different stratum 1 clock than the master in Datacenter B. The NTP client in office A uses different masters than clients in office B. Building a hundred cases into my template file to cover all the variations is completely unmanageable. I want to be able to set defaults for certain zones and then be able to override them. Puppet seems to be _completely_ against that philosophy. I also do not like the idea of mixing a module definition (which covers things like required packages and services) with specific settings like server names (even if the server name is part of a case statement in the template). My templates are all _completely_ generic. I can use them in any site by altering the variables I pass in. (I have used $ldap_server as a variable to determine whether or not to include the slapd.conf and openldap-servers packages- but that doesn''t obviate the need to be able to set values for the variables I need to pass into the templates).> That way it does not matter what the server name is > or where it is. If it is defined as have having a ntp server role then > it gets that configuration.Of course it matters where the server is. Different sites have different reference clocks, different masters, different ACL''s. The "role" is fine for defining what packages to include, I need "zones" which allow me to specify default settings for the packages in those roles! Without that I either need to split my specific settings up into dozens of modules and try to manage them that way (which is silly given that there is bound to be overlap between settings and one of the first rules of normalization is to avoid duplication) or establish a completely flat node hierarchy which will also include lots of duplication.> One of the strengths I have found in > templates is that you can but the logic in the template.This means that to change something like an ACL, which might be the same across several different services, you now need to change it in several templates, or several node definitions. That can not be considered a good way to do things. I feel like the right way to do this is simple: I define zones (or sites or environments or whatever). Each has certain values set and subsequent includes override previous ones. For example: class zone::global { $ldap_base = "dc=example,dc=com" $ldap_servers = [''ldap01.example.com'', ''ldap02.example.com''] $ntp_servers = [''ntp01.example.com'', ''ntp02.example.com''] $ntp_acls = [''''] $my_domain = "example.com" } class zones::nyc { $ldap_base = "dc=nyc,dc=example,dc=com" $ldap_servers = [''ldap01.nyc.example.com'', ''ldap02.nyc.example.com''] $my_domain = "nyc.example.com" } class: roles::general { include ldap include ntp include resolver } class roles::ldapserver { $ldap_server = true include roles::webserver } node www02.example.com { $ldap_servers = [''ldaptest1.nyc.example.com'', ''ldaptest2.example.com''] include zones::global include roles::general include roles::webserver } node host1.nyc.example.com { $ldap_servertype = "slave" include zones::global include zones::nyc include roles::general include roles::ldapserver } In the last node example I defined roles::ldapserver. That role specifies the packages to be installed for an ldap server, as well as the server type. It still includes the ldap base ldap module, but with some additional packages and possibly with some additional default values passed in. That allows me to keep all my settings (roles, zones, etc.) in /etc/ puppet/manifests and my modules in /etc/puppet/modules thus preserving a division between settings and implementation. It also lets me see, at a glance, what I am including and what I''m excluding. I don''t need to look into a specific module template to see what settings may or may not be enabled. It''s right there in the manifests directory where I am already working. It also means I can share modules much more easily. Am I nuts in thinking that this is a better organizational style? The puppet books talks about workarounds for some of these problems. Should we be working around these issues or do they need to be "fixed"? Perhaps there is a serious implication for the language that I''ve completely missed- if so- please let me know. -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Don
2009-Jun-24 02:54 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
Ack- sorry I got my examples backwards- The overrides should have come after the included classes like so:> node www02.example.com { > include zones::global > > include roles::general > include roles::webserver > > $ldap_servers = [''ldaptest1.nyc.example.com'', > ''ldaptest2.example.com''] > > } > > node host1.nyc.example.com { > include zones::global > include zones::nyc > > include roles::general > include roles::ldapserver > > $ldap_servertype = "slave" > }Sorry for the confusion (and the previous absurdly long email). -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Evan Hisey
2009-Jun-24 19:51 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
On Tue, Jun 23, 2009 at 9:54 PM, Don<don@blacksun.org> wrote:> > Ack- sorry I got my examples backwards- The overrides should have come > after the included classes like so: > >> node www02.example.com { >> include zones::global >> >> include roles::general >> include roles::webserver >> >> $ldap_servers = [''ldaptest1.nyc.example.com'', >> ''ldaptest2.example.com''] >> >> } >> >> node host1.nyc.example.com { >> include zones::global >> include zones::nyc >> >> include roles::general >> include roles::ldapserver >> >> $ldap_servertype = "slave" >> } > > Sorry for the confusion (and the previous absurdly long email). >Long yes, but it did help define your issue. I think the first layout would be a more correct one, and from my experience should work, I think. Have you tried doing zones::global and zones::nyc as inherits? When you then redefine the variables in the node definition they should override the settings in the inheritance. Inheritance puts things in the parent scope and includes puts variables in the child scope> This means that to change something like an ACL, which might be the > same across several different services, you now need to change it in > several templates, or several node definitions. That can not be > considered a good way to do things.This type of situation where you have the same thing defined across several nodes is in theory best handled by virtual resources. I have encountered similar issues and that is the advice I got. I am still working on making that change so am not sure who much use my explaining virtual resources will be. As a general thought, looking at the complexity you have, are you using external node definitions? From what I have read on the list and about you site that looks like it would be extremely useful to you and possible something using stored configs could help resolve your issues. Evan --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Don
2009-Jun-24 22:10 UTC
[Puppet Users] Re: Server Hierarchies and other configuration questions
> Long yes, but it did help define your issue. I think the first layout > would be a more correct one, and from my experience should work, I > think. Have you tried doing zones::global and zones::nyc as inherits? > When you then redefine the variables in the node definition they > should override the settings in the inheritance. Inheritance puts > things in the parent scope and includes puts variables in the child > scopeI thought variables you inherited would already be set and thus unchangeable. I''m testing this now but it seems to work. Thanks for the insight. All the docs I''ve seen suggest using node inheritance to manage "roles" but it seems to me that we should be using classes to manage roles and inheritance to handle variables. It''s not as clean because you can''t see at a glance what variables a node is inheriting (because you can only inherit one other node and thus have to build a node tree- but at least this seems to work. I''m going to go test this now and see if I can get it to do everything I want. It definitely looks like progress.> > This means that to change something like an ACL, which might be the > > same across several different services, you now need to change it in > > several templates, or several node definitions. That can not be > > considered a good way to do things. > This type of situation where you have the same thing defined across > several nodes is in theory best handled by virtual resources. I have > encountered similar issues and that is the advice I got. I am still > working on making that change so am not sure who much use my > explaining virtual resources will be.Virtual resources could work, but it seems overly complex for what i''m trying to do. It''s not so much that I''m trying to define the same object across multiple resources, but more a specific variable. Having to create a virtual resource and then instantiate it every time I add a new ACL seems to be a lot more trouble than just setting my ACL variable appropriately.> As a general thought, looking at the complexity you have, are you > using external node definitions? From what I have read on the list and > about you site that looks like it would be extremely useful to you and > possible something using stored configs could help resolve your > issues.I already run LDAP but haven''t moved my nodes into it yet. I don''t want to go to all that trouble until I''m sure I can resolve some of these hierarchy issues. Just moving the values into ldap won''t help unless I start writing all sort of functions in puppet to query resources and configure them appropriately. Again- that''s way more trouble than I''m willing to deal with. At that point I might as well invest the time and effort to learn Chef as it seems to have native support for overrides. I just wish I knew why puppet was designed in the way it was sometimes. Scoping makes sense in a lot of languages, but here it just seems to get in the way. Ditto for the declarative nature of the language. -Don --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---