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
-~----------~----~----~----~------~----~------~--~---

Reply via email to