Hey Asif, On Wed, Jul 15, 2009 at 12:51 PM, Asif Iqbal <vad...@gmail.com> wrote:
> > Hi > > I am looking for recipe or some hints to a recipe that can help me > achieve the following > > I have about 300 servers of different functions. To make it easy I > decided to keep multiple group dirs based on the > function and have hosts,passwd,users,sudoers file located inside those > function dirs, like the following. What do you mean by group dirs in this context? I am assuming you me host groups base on node function. For clarity, I will call them functional groups. In this > example dns is the function of the hosts listed w/ fqdn in the hosts > file. The passwd and shadow are going to be > same as the /etc/passwd and /etc/shadow file for all these hosts, same > for sudeors. users is list of users. may have no purpose > right now. So, we are talking about a dns functional group based on the FQDN. In general, I avoid using metadata in the FQDN as a means to classify a given node. Classification is a human assignment, so I just classify using my node tool (site.pp or external) as the database instead of some conditional statement base on FQDN. I know this is unorthodox, but I have good reason for despising metadata based hostnames. ( Hostnames make a sorry database! Rant available upon request. ) Secondly, just for a simplification you can use a single sudoers file for all of your host. You can specify access based on host groups in the sudoers file itself. There are some cases (security domains) where you may want to avoid this, but in general I use one sudoers to rule them all. (root)@puppetmaster:/path/to/groups# ls -lR dns/ > dns/: > total 11 > -rw------- 1 root other 1 Aug 23 2005 hosts > -r--r--r-- 1 root other 33 Aug 22 2005 passwd > -r-------- 1 root other 31 Aug 22 2005 shadow > -r--r----- 1 root root 546 Aug 27 2005 sudoers > -rw-r--r-- 1 root other 152 Feb 21 2006 users > Ok, here is the Puppety part and it is really about organization and reuse. Forget this host group organizational structure. It is going to be nothing but trouble in the long run. Lets think of classes instead as a way to specify configurations via composition and inheritance and lets use modules exclusively. Explicitly lets create two module paths: /path/to/modules/dist: Is where you will build small reusable modules that will be used to compose class that classify your services. And... /path/to/modules/site is where you will build larger modules and create complex composite configurations. Here you will include classes from the dist path. I would avoid including site classes in the classes defined in the dist path. I like to have the dependencies flow one way. Ok, so in the site module path lets create a module called acme. And reorganize based on this structure: /path/to/modules/site/acme > currently, I have a test site.pp like this > > # site.pp > > node basenode { > case $hostname { > puppet-test: {} > default: {} > } > } > K, I would avoid doing the condition stuff here. Instead if we have a node foo lets just assign it the base class acme from our acme module. This will make our site.pp compatible with an external nodes tool. node foo { acme: } On a side note, no need for client server when if we are testing. Just checkout the dev branch of your puppet modules on the test node, use the puppet executable and pass it a test.pp that includes the classes that you want to test like so: puppet --debug --modulepath=/path/to/modules/dist:/path/to/modules/site test.pp This is how I training people to develop their puppet code in our classes. Try it; you'll like it! Alright, so here we go refactoring this we would have a acme::dns class in our acme module that would include or inherit all the smaller classes that are needed to setup a DNS host. > > node 'puppet-test' { > include dns > include sudo > } So our node definition would now look like... node 'puppet-test.fqdn.org' { include acme::dns } Again, I prefer simple assignment. Essentially, one class included per node. I do all the specification that is role based in classes. If an individual host needs specific parameters set, I either handle that logically inside the classes or assign parameters to the host (External Nodes supports this better). This allows me to test composite classes as part of the module development process. We would refactor this class then: > > class dns_users { > @user { "testuser": > ensure => "present", > uid => "102", > gid => "1", > comment => "test user", > home => "/home/testuser", > shell => "/bin/bash", > managehome => "true", > } > } > Becoming a single virtusers class: class acme::virtusers { @user{ testuser: ensure => "present", uid => "102", gid => "1", comment => "test user", home => "/home/testuser", shell => "/bin/bash", managehome => "true", tag => dns; # Yup a tag! foouser: ensure => "present", uid => "103", gid => "1", comment => "test user", home => "/home/foouser", shell => "/bin/bash", managehome => "true", tag => webserver; # MMMM tags! } } We include acme:virtuser in the acme base class. Then when you want to include a user or set of users in a given role, for example in class acme::dns, just realize that user or set of users based on a tag. In this case, we are going to use the dns tag that we set using the tag metaparameter. class acme { ... include virtusers } class acme::dns { include acme # this includes all the base stuff including acme::virtusers User <| tag == dns|> #this realizes the virtual users tag with dns } We replaced this with acme::dns above. class dns { > include dns_users > realize( > User["testuser"] > ) > } > I would expect a generic reusable bind or dns module in the dist module path that handles installing packages or any other resources you may want to manage. As we develo, a shareable module repo, this directory may be populated with reusable modules sourced from the interwebs and maintained by the community. > > class sudo { > file { sudoers: # a common title for all platforms > path => $operatingsystem ? { > solaris => "/opt/csw/etc/sudoers", > default => "/etc/sudoers" > }, > owner => root, > group => root, > mode => 440, > source => "puppet:///sudo/sudoers" > } > } This would go in a generic sudoers module in dist. If you really really need to use a different sudo for each role then inheritance is your friend. class acme::dns::sudo inherits sudo { ... File['sudoers': source => puppet:///acme/dns/sudoers] # Simply overriding the source parameter. } and in acme::dns: class acme::dns { include acme::dns::sudo } > Instead of creating 300 manifests and that many more users in the > class and/or @users I like to see if there is maybe a template can be > created. > So when the puppet client comes to puppetmaster, based on the fqdn of > the host it will be assigned as part of a group. Then based on the > assigned So with the refactor that I have suggested, you should be able to avoid the duplication and make the code manageable. I still would avoid the FQDN based class assignment if possible though. I am prejudiced. > > group it will receive specific sudoers file and a list of users will > be created based on the values in passwd and shadow files. > Looking for recipe to achieve that. > > Thanks Code reuse, clean organization, reduction of conditionals, and simple assignment... FTW. -- > Asif Iqbal > PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu > A: Because it messes up the order in which people normally read text. > Q: Why is top-posting such a bad thing? > > > > Cheers, Teyo -- Teyo Tyree :: www.reductivelabs.com --~--~---------~--~----~------------~-------~--~----~ 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+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---