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