Thanks for the response.
Can multiple classes include the same class. Let's say I instantiate the apache class from manifests/nodes.pp which in turns includes apache::params. Can kibana include apache::params then as well with no conflict. I know you can't do this with the class {} style declarations. Also, I thought the class {} style declarations were the preferred way or is that just in the nodes.pp file?
The only way to force parse-time ordering right now is to do a direct
include, unfortunately.
I'm not sure I fully agree with this from a design standpoint. In object-oriented programming, one of the design principles is that variables relating to the object are encapsulated within the object and exposed or not depending on how they should be accessed. IMHO, it also makes it more obfuscated when you're accessing say the SSL CA cert path variable and that's in some 'common' module that everything has to include. Granted it makes it easier on the module developer - just always in include the common module and your variables should be there - but it also makes it less explicit.
I include that in the module that installs the shell packages and configures them, in my case, I call it base. In other words, the variables should be as close to the things they affect or are affected by. Just because every node might include base (or site) doesn't mean every variable you'll ever want to use should be in there. That, to me, creates a messier and more confusing dependency relationship between modules that use a variable and what that variable ultimately affects.
On Jan 29, 2013, at 8:51 AM, jcbollinger wrote:
>> The only way to force parse-time ordering right now is to do a direct
>> include, unfortunately.
>>
>
>
> Yes, but I'm not sure I would say "unfortunately" there. The problem is not so much with any limitation of Puppet DSL in this area, but rather an issue of module design and manifest set architecture.
>
> I mean, one should be very careful and deliberate about designing modules such that their classes need to rely on class variables of other modules' classes. Indeed, it is probably a poor idea to implement such a design unilaterally -- instead, the module providing the class variables should be designed and implemented in anticipation of that usage as well. That probably means centralizing all variables intended for cross-module reference in one well-known class, documenting their names and value ranges, and committing to avoiding incompatible changes there.
>
I'm not sure I fully agree with this from a design standpoint. In object-oriented programming, one of the design principles is that variables relating to the object are encapsulated within the object and exposed or not depending on how they should be accessed.
IMHO, it also makes it more obfuscated when you're accessing say the SSL CA cert path variable and that's in some 'common' module that everything has to include.
Granted it makes it easier on the module developer - just always in include the common module and your variables should be there - but it also makes it less explicit. I would argue, if you're writing a module that depends on using the SSL CA cert path you have some dependency on the SSL module and should have some understanding of what that module does and the ramifications of using that module, so you should explicitly include that module for that dependency. In just about every language you must include the external modules/libraries you depend on for functionality outside the standard norm. In puppet the standard norm - the stdlib.h equivalent if you will - I would consider to be facter variables. You want to use LDAP or SSL or Kerberos? You best include those modules explicitly and figure out what you can use from them - ldap.h <> ldap::params, ssl.h <> ssl::params, etc. Standardize how you create these public puppet 'headers' and use them explicitly and appropriately that way.
On Jan 30, 2013, at 9:31 AM, jcbollinger wrote:
[...]
> And now that you drop the idea of a common data module, we come back around to using other modules' classes' variables. Are you honestly arguing that it is better to analyze class implementations and pull out variables willy-nilly than to define and rely on documented interfaces? I think you owe a penance at the OO altar.
>
I'm arguing that no more than I would argue having to delve into the source code of openssl in order to use it in my C program - that's what the header is for. I'm arguing to define your class implementations such that the nitty gritty of that class' implementation need not be inspected in order for another module to make use of it,
not mash all the public bits in to one globally public class that has no nitty gritty bits to implement. In my example <module>::params is considered the header for the module (granted a header that exposes values, but that can't be helped due to the declarative nature of the DSL). There should be no implementation in that sub-module and even <module> should reference that 'header' to get the variables it needs to do its work. But I'll still pay penance at the OO altar for all my past transgressions against and abuses of it.
On Jan 30, 2013, at 2:33 PM, jcbollinger wrote:
>> not mash all the public bits in to one globally public class that has no nitty gritty bits to implement. In my example <module>::params is considered the header for the module (granted a header that exposes values, but that can't be helped due to the declarative nature of the DSL). There should be no implementation in that sub-module and even <module> should reference that 'header' to get the variables it needs to do its work. But I'll still pay penance at the OO altar for all my past transgressions against and abuses of it.
>>
>
>
> Maybe we're just having a terminology problem. Puppet has no concept of sub-modules, and the only construct available to hold reference-able, non-global variables is the class. Indeed, even modules themselves are a Puppet implementation detail -- the DSL has no concept of them except as top-level namespaces (but top-level namespaces often map to classes, either instead of or in addition to mapping to modules).
>
> So, would you care to explain how your <module>::params then differs from "mash[ing] all the public bits in to one globally public class that has no nitty gritty bits to implement"? Are you suggesting separate ::params classes shadowing multiple different classes in the same module? Are you conflating class parameters with class variables?
>
Let's go back to my original example from http://pastie.org/5910079#. Not stated in that code snip (for conciseness) is a module, kibana. Among other things it needs to install an apache configuration to make it a useful piece of software and that configuration is in the kibana::apache sub-class in the form of a snippet that is tagged such that the apache module can instantiate it later on at the proper time (there's an alternative to this method). In order to do this, the kibana::apache class needs to know where to install this configuration file so that the apache process can load it. That location I chose to place in a variable, $config_d, in the apache module in a sub-class (sorry for the improper nomenclature before) apache::params. To solve my original problem I simply add:
include 'apache::params'
On Jan 30, 2013, at 2:33 PM, jcbollinger wrote:
> Maybe we're just having a terminology problem. Puppet has no concept of sub-modules, and the only construct available to hold reference-able, non-global variables is the class. Indeed, even modules themselves are a Puppet implementation detail -- the DSL has no concept of them except as top-level namespaces (but top-level namespaces often map to classes, either instead of or in addition to mapping to modules).
>
> So, would you care to explain how your <module>::params then differs from "mash[ing] all the public bits in to one globally public class that has no nitty gritty bits to implement"? Are you suggesting separate ::params classes shadowing multiple different classes in the same module? Are you conflating class parameters with class variables?
>
Let's go back to my original example from http://pastie.org/5910079#. Not stated in that code snip (for conciseness) is a module, kibana. Among other things it needs to install an apache configuration to make it a useful piece of software and that configuration is in the kibana::apache sub-class in the form of a snippet that is tagged such that the apache module can instantiate it later on at the proper time (there's an alternative to this method). In order to do this, the kibana::apache class needs to know where to install this configuration file so that the apache process can load it. That location I chose to place in a variable, $config_d, in the apache module in a sub-class (sorry for the improper nomenclature before) apache::params. To solve my original problem I simply add:
include 'apache::params'
right above the @file snippet in kibana::apache and everything is happy. I think everyone can agree that is the right solution to the problem that I posed; however, both you and Luke strongly suggested against having modules include other module's variables willy nilly and instead move those variables that multiple modules need to reference into a globally included class, we'll call it globals::.