On Wednesday, March 11, 2015 at 4:35:36 PM UTC, Bostjan Skufca wrote: > > > >> Something like this seems like I'm telling a module *how* to look up my >> own data, rather than passing the right data to the module: >> >> >> class resolv ( >> $dns_servers_key_name = 'dns_servers', >> $dns_servers_key_merge = false, >> ) { >> if ($dns_servers_key_merge) { >> $dns_servers = hiera_array($dns_servers_key_name) >> } else { >> $dns_servers = hiera($dns_servers_key_name) >> } >> } >> >> class { 'resolv': dns_servers_key_merge => true } >> >> >> I'd also have to code it to selectively use Hiera or not (some people >> don't) and that would get even worse. The second example of module design >> may be super awesomely flexible in terms of how I can structure my Hiera >> data, but it doesn't fit the direction the community is moving in terms of >> module design. >> > > > This is almost what I am looking for. I have an alternate approach: what > if merging vs nonmerging is decided based on hiera key? > >
That is my approach, that class would do an implicit Hiera lookup for those class parameters, I just illustrated the point with a resource-like declaration as an example. While the above method would work, I don't think I've made my point about not putting this personalised logic in the "resolv" module itself. The above example is not so good. Gary Larizza explains it very well here if you haven't seen it (https://www.youtube.com/watch?v=v9LB-NX4_KQ). That video should answer your questions in your second reply to me too, BTW. The above code example is a bad idea for these reasons: - the resolv module is tightly coupled to the data, it's in control of how it should look up data, rather than just be *given* data - you won't be able to replace that resolv module with the super awesome puppetlabs_resolv module because of your custom way of handling data - it makes a *very* bad assumption that everyone uses Hiera, it is not compatible for people who use ENCs that supply all class parameters for example - there's a higher barrier to entry on understanding the module, some people would have to read the body of the resolv module code to figure out what's going on (or there would be a long README) - it's more complicated to test because the range of data it can take is more complicated Now expand on my first example: ******************** class puppetlabs_resolv($dns_servers) { file { '/etc/resolv.conf': content => template(...) } } class profile::dns_base { #lookup my DNS data from Hiera $hiera_dns_server_array = hiera_array('dns::server') #and add a global DNS server I have $common_dns_server = '127.0.0.1' class { 'puppetlabs_resolv': dns_servers => [ $hiera_dns_server_array, $common_dns_server ] } } class profile::dns_special { #don't do a hiera lookup, DNS here is special $special_dns = '10.1.1.1' class { 'puppetlabs_resolv': dns_servers => [ $special_dns ] } } node dc1 { include profile::dns } node dc1_special { include profile::dns_special } ******************** The puppetlabs_resolv module I downloaded from GitHub does one thing well, resolv.conf, in a simple and easily understood manner, and it comes with Rspec tests, so I don't have to reinvent the wheel. All of my business logic about how I get IP addresses into that resolv module is in my profile::dns* classes. These are *my* profile classes, I can do whatever crazy Hiera lookups and string manipulation I want/need to get the data into a format that puppetlabs_resolv takes. In other words my profiles are the "glue" between my data and the "building block" puppetlabs_resolv module. At any time I can replace puppetlabs_resolv with lukebigum_resolv (which is obviously better) with a few tweaks to my profiles. If I replace my data backend or get rid of Hiera entirely, my profile might have to be adjusted but I don't have to stop using that awesome lukebigum_resolv I downloaded. Why the use of a second profile, profile::dns_special? It takes complexity out of Hiera. I don't need a complicated Hierarchy when I've got profiles, and I rarely need inheritance at all. I've got my "tpl_%{::domain}" which is where my profile::dns looks up data from, and anything that's special is actually a different implementation of how I usually do DNS, so it gets it's own profile, hence profile::dns_special. It is better to handle these exceptions in Puppet code because it's an *actual* language, rather than trying to model something complex into Hiera which is just a key-value store. Your Hiera example where you have tpl_dc1.yaml and tpl_dc1-special.yaml is going to bite you. Your joke about mimicking node inheritance functionality in Hiera worries me a little, because it reminds me of some of my colleagues. Just because it can be modelled in Hiera, doesn't mean it should be. To give you an example, at my work place we can build an entire platform where each node's Hiera file looks like this: --- ip_address_fourth_octet: 10 And the rest is abstracted, inherited and hidden away. In some ways it's really awesome, but it is also very hard to debug, and extraordinarily hard to understand. I once spent 2 hours tracing a string in a configuration file through too many Hiera files each with over a dozen levels of dictionary/hash depth, about 7 create_resource() calls, several exported resources and luckily only 3-4 recursive Hiera lookups. I was not happy by the end of that. Not long after my team lead forced us to re-read the Roles and Profiles design pattern and to watch that video ;-) My recommendation to you is to seriously look at why you're relying on inheritance and merging so much, I think you could simplify a lot more. If you post a more relevant example and your Hierarchy, I'd be happy to discuss. -Luke -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/9b37aec0-a457-4023-8f2c-d4cfee4f3220%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.