Brian, Thanks for adding this to the wiki! Glad you found it useful.
--Paul On Tue, Feb 10, 2009 at 10:00 AM, Brian Finney <b...@nfinney.com> wrote: > > As this is the best explanation of how to approach this problem I have > ever seen, I took the liberty of adding it to the wiki at > http://reductivelabs.com/trac/puppet/wiki/Recipes/HandlingDisparateDefinesWithClasses > and linked it from the external nodes intro. Thanks Paul > > Brian > > On Tue, Feb 10, 2009 at 1:08 AM, Paul Lathrop <p...@tertiusfamily.net> wrote: >> >> Nicolas, >> >> I split this thread since we aren't talking about Kinial anymore. >> >> I think you misunderstood me; I certainly wouldn't advocate the >> mishmash of classes you suggest below, as you said, putting the >> definition "calls" (I use "declarations", and will in the rest of this >> email) in the node statements is easier and more maintainable. Your >> problem is a good one, and similar to one I have encountered in my use >> of Puppet. The issue at hand seems to be "I'd like to use external >> nodes, but I can't because I'd lose the ability to declare defined >> resources at the node level." This is the issue I'm addressing, so if >> I'm wrong about the problem, let me know. >> >> There are a couple of approaches to the problem you describe. The >> first step is almost always to take a step back and ask yourself if >> you have designed your solution in a way that makes the best use of >> the tools you've chosen. Puppet shines at creating repeatable >> configurations across a number of machines; creating mostly similar, >> but somewhat different configurations on each individual machine, >> while a related problem, is not the same thing. So, one thing I might >> ask myself in the situation you describe is this: does each machine >> really need to have a different set of webapp-instances? Are there >> resource constraints, or are you just following a (reasonable!) habit >> of only putting what is necessary on any given server? If you find >> that there really isn't any reason, you can address this problem by >> creating a class that defines all the webapp-instances and including >> that class on every node. >> >> To make the solution more interesting, though, let's assume that there >> is a solid reason not to deploy all the countries to every application >> server. The next question we ask is: how can we put these definitions >> within a class without losing the flexibility/maintainability we get >> from node-level declarations? Depending on the internal implementation >> of your definition, Puppet arrays might come to your rescue: >> >> node node1 { >> countries = ["es", "fr", "uk"] >> include webapp >> } >> >> node node2 { >> countries = ["es", "it", "de"] >> include webapp >> } >> >> class webapp { >> webapp-instance { >> "app": >> countries => $countries; >> } >> } >> >> We had a similar issue that I dealt with in a slightly different way. >> We have this concept of database instances that have a name (a >> numerical id of the "slot" of the instance), a port they run on, and a >> replication statement. So we have something like: >> >> define db::instance($port, $replicate_db) >> >> The instances required vary by machine, a specific instance isn't >> always on a given port, etc. So I had trouble mapping this to classes >> (especially for machines that needed multiple instances of the same >> "type" running on different ports). For a long time we did this at the >> node level: >> >> node qa-db { >> db::instance { >> "0": >> port => 3306, >> replicate_db => production; >> "1": >> port => 3307, >> replicate_db => production; >> } >> } >> >> Then we decided to switch to external nodes... and there was a bit of >> trouble. It was easy enough to write classes for each instance type >> and set a variable for the slot, but I ht a wall on machines that >> needed multiple instances that were identical except for slot#/port. >> Then I remembered arrays: >> >> class zomg_read { >> db::instance { >> $zomg_read_slot: >> port => $zomg_read_slot + 3306, >> replicate_db => production; >> } >> } >> >> node qa-db { >> $zomg_read_slot = [0, 1] >> include zomg_read >> } >> >> Since using arrays creates multiple resources, this works really well, >> and pulls the definitions into a class without losing the flexibility >> required to migrate to external nodes. >> >> Obviously, not knowing everything about your situation, I can't solve >> your problem completely but I can say that, in my experience, when the >> tool seems like it is getting in my way I am often not using the tool >> the way it was designed to be used. Puppet is a somewhat opinionated >> tool, in some ways, in that there are design decisions made to support >> the Puppet model of the world, and you may have to adjust your design >> to fit that model (or pick a different tool, I suppose). Not that we >> can't change the tool where merited, but in this case, I think Puppet >> has it right. >> >> --Paul >> >> On Tue, Feb 10, 2009 at 12:16 AM, nicolas <ncapp...@yahoo.fr> wrote: >>> ok paul, thanks for clarifying this. >>> >>> I think my misconception comes from what we're trying to do. >>> >>> We have webapps that have instances defined for different set of >>> countries >>> So we have definitions like : >>> define webapp-instance($countries, ...) >>> >>> And then for a set of machines we want to deploy our instances, but no >>> machine has the exact same requirement : >>> node node1 { >>> webapp-instance { "es_fr", countries = ["es", "fr"] } >>> webapp-instance { "uk", countries = ["uk"] } >>> } >>> node node2 { >>> webapp-instance { "es_it", countries = ["es", "it"] } >>> webapp-instance { "de", countries = ["de"] } >>> } >>> and so on... >>> >>> So, if I follow your guidelines, I should define intermediate classes >>> and then use theses classes in the nodes >>> class webapp_instance_es_fr { >>> webapp-instance { "es_fr", countries = ["es", "fr"] } >>> } >>> >>> class webapp_instance_uk { >>> webapp-instance { "uk", countries = ["uk"] } >>> } >>> >>> class webapp_instance_"de" { >>> webapp-instance { "de", countries = ["de"] } >>> } >>> >>> and then put theses classes in my nodes : >>> node node1 { >>> include webapp_instance_es_fr >>> include webapp_instance_uk >>> } >>> >>> Although this step makes sense, it happens that using "definition >>> call" (how should I say ?) directly in nodes is easier because people >>> in charge of managing nodes don't have to write intermediate classes >>> that only act as wrapper. >>> As there is almost no machine with the same country configuration >>> (that is, a class will only be used by one machine in practice), the >>> overhead of writing intermediate classes gives no real benefits, even >>> if conceptually cleaner. >>> >>> Any comment on this ? >>> >>> thanks >>> >>> nicolas >>> >>> >>> > >>> >> >> > >> > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---