I''d like to create a component that takes different actions based on the classes associated with the node using the component. Is this possible? Here''s what I''m thinking. node www01 { include webserver website { "site1.com": aliases => ["www.site1.com", "test.site1.com"], username => www0001 } } node www02 { include webserver website { "site2.com": aliases => ["www.site2.com", "test.site2.com"], username => www0002 } } node nfs1 { include nfs-server website { "site1.com": username => www0001; "site2.com": username => www0002; } } define website(aliases, username, uid, gid) { $domain = $name # do some magic in here so this only applies webserver nodes file { "/etc/lighttpd/sites-enabled/$domain.conf" : owner => root, group => root, mode => 644, require => package[lighttpd], notify => service[lighttpd], content => template("website.conf.erb"), } # and do some other stuff on the nfs-server nodes file { "/export/www/sites/$domain" : source => "...", recurse => true, } } How should I go about doing this? Thanks, Christian
Christian G. Warden wrote:> I''d like to create a component that takes different actions based on the > classes associated with the node using the component. Is this possible?Yes it is, but I''ll warn you that here be dragons, kind of. This is one of the areas in which Puppet''s language is not sufficiently declarative, in a way that I''ll only be able to fix by making it a two-pass parser. It is *highly* likely that I''m going to change something at some point that will make this actually declarative -- this won''t mess you up as long as you never depend on file ordering, but I''m not willing to make guarantees right now that it will always behave consistently. Anyway: You can use the ''tagged'' function to test which classes have been included, as long as that class is included *before* you call ''tagged''. So, using your example, you could write ''website'' like this: define website(aliases, username, uid, gid) { $domain = $name case tagged(webserver) { true: { file { "/etc/lighttpd/sites-enabled/$domain.conf" : owner => root, group => root, mode => 644, require => package[lighttpd], notify => service[lighttpd], content => template("website.conf.erb"), } } false: { # and do some other stuff on the nfs-server nodes file { "/export/www/sites/$domain" : source => "...", recurse => true, } } } } 0.19.0 has an if/else structure that would clearly work better here. You may want to consider a simpler structure, too: define website(aliases, username, uid, gid) { $domain = $name file { "http-$domain-config": path => tagged(webserver) ? { true => "/etc/lighttpd/sites-enabled/$domain.conf", false => "/export/www/sites/$domain", }, ... } } Depending on how similar your statements are. There''s also a ''tag'' function you can use, just to tag a host without having there be a related class. These tags are basically booleans, and every evaluated class sets one, but only after its been evaluated or during the evaluation. -- A Chemical Limerick: A mosquito cried out in pain: "A chemist has poisoned my brain!" The cause of his sorrow was para-dichloro diphenyltrichloroethane -- Dr. D. D. Perrin --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com
On Fri, Sep 01, 2006 at 08:24:49PM -0500, Luke Kanies wrote:> Christian G. Warden wrote: > > I''d like to create a component that takes different actions based on the > > classes associated with the node using the component. Is this possible? > > Yes it is, but I''ll warn you that here be dragons, kind of. > > This is one of the areas in which Puppet''s language is not sufficiently > declarative, in a way that I''ll only be able to fix by making it a > two-pass parser. It is *highly* likely that I''m going to change > something at some point that will make this actually declarative -- this > won''t mess you up as long as you never depend on file ordering, but I''m > not willing to make guarantees right now that it will always behave > consistently. > > Anyway: You can use the ''tagged'' function to test which classes have > been included, as long as that class is included *before* you call > ''tagged''. So, using your example, you could write ''website'' like this: > > define website(aliases, username, uid, gid) { > $domain = $name > case tagged(webserver) { > true: { > file { "/etc/lighttpd/sites-enabled/$domain.conf" : > owner => root, > group => root, > mode => 644, > require => package[lighttpd], > notify => service[lighttpd], > content => template("website.conf.erb"), > } > } > false: { > # and do some other stuff on the nfs-server nodes > file { "/export/www/sites/$domain" : > source => "...", > recurse => true, > } > } > } > } > > There''s also a ''tag'' function you can use, just to tag a host without > having there be a related class. > > These tags are basically booleans, and every evaluated class sets one, > but only after its been evaluated or during the evaluation.Thanks. Using an explicit tag will probably be safer since it will be clear that the tag needs to be created before referenced within the component. Christian
On Fri, Sep 01, 2006 at 08:24:49PM -0500, Luke Kanies wrote:> Christian G. Warden wrote: > > I''d like to create a component that takes different actions based on the > > classes associated with the node using the component. Is this possible? > > Yes it is, but I''ll warn you that here be dragons, kind of. > > This is one of the areas in which Puppet''s language is not sufficiently > declarative, in a way that I''ll only be able to fix by making it a > two-pass parser. It is *highly* likely that I''m going to change > something at some point that will make this actually declarative -- this > won''t mess you up as long as you never depend on file ordering, but I''m > not willing to make guarantees right now that it will always behave > consistently. > > Anyway: You can use the ''tagged'' function to test which classes have > been included, as long as that class is included *before* you call > ''tagged''.The ability to use ''node'' multiple times in the manifest would be useful in this type of situation so you could do something like this: node www01,www02 { include webserver } node fs01 { include nfsserver } node www01, fs01 { website { "site1.example.com": } } node www02, fs01 { website { "site2.example.com": } } Christian
On Sep 6, 2006, at 8:04 PM, Christian G. Warden wrote:> > The ability to use ''node'' multiple times in the manifest would be > useful in > this type of situation so you could do something like this:[SNIP] Yeah, I''ve been pondering something like this for both nodes and classes. It would likely be relatively straightforward for nodes, but if we ever supported some kind of parameterization within classes it would be very complicated. I''ll add this to the dev list, because I think something like it should be possible, just like how Ruby allows you to add code to classes. -- Luke Kanies http://madstop.com | http://reductivelabs.com | 615-594-8199