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 <ncapponi@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+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en
-~----------~----~----~----~------~----~------~--~---
Brian Finney
2009-Feb-10 18:00 UTC
[Puppet Users] Re: Definitions, Classes, and Nodes; Oh My!
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 <paul@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 <ncapponi@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+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Paul Lathrop
2009-Feb-10 18:24 UTC
[Puppet Users] Re: Definitions, Classes, and Nodes; Oh My!
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 <bri@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 <paul@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 <ncapponi@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+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Benoit Decherf
2009-Feb-11 13:05 UTC
[Puppet Users] Re: Definitions, Classes, and Nodes; Oh My!
Thanks for that very good explication !
I still have a doubt : How to manage property "per instance".
In a little more complicated case, an instance of a webapp have to
connect to a given database.
node node1 {
$countries=["fr", "uk"]
include webserver
}
and my webserver class:
class webserver {
webapp-instance{$countries:
database => ${db_ip_${country}}
}
}
of course this doesn''t works ;)
How do you manage this ?
hashes aren''t supported by puppet, so this is not a solution.
To make it work I make a function "eval" which lookup for the value in
the scope and do something like:
webapp-instance{$countries:
database => eval(db_ip_${country})
}
But this is a hack. What is the correct way to do this ?
On 02/10/2009 10:08 AM, Paul Lathrop 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<ncapponi@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+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en
-~----------~----~----~----~------~----~------~--~---
Paul Lathrop
2009-Feb-11 18:08 UTC
[Puppet Users] Re: Definitions, Classes, and Nodes; Oh My!
Benoit, This doesn''t seem like a hack to me. I think this is the correct way to approach the problem you describe. --Paul On Wed, Feb 11, 2009 at 5:05 AM, Benoit Decherf <decherfb@yahoo-inc.com> wrote:> Thanks for that very good explication ! > > I still have a doubt : How to manage property "per instance". > In a little more complicated case, an instance of a webapp have to connect > to a given database. > > node node1 { > $countries=["fr", "uk"] > include webserver > } > > and my webserver class: > > class webserver { > webapp-instance{$countries: > database => ${db_ip_${country}} > } > } > > of course this doesn''t works ;) > How do you manage this ? > > hashes aren''t supported by puppet, so this is not a solution. > To make it work I make a function "eval" which lookup for the value in the > scope and do something like: > webapp-instance{$countries: > database => eval(db_ip_${country}) > } > > But this is a hack. What is the correct way to do this ? > > > > On 02/10/2009 10:08 AM, Paul Lathrop 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 <ncapponi@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+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---