On Thursday, May 15, 2014 9:55:05 PM UTC+2, John Bollinger wrote:
>
>
>
> On Thursday, May 15, 2014 9:46:40 AM UTC-5, Alessandro Franceschi wrote:
>>
>> Hallo everybody,
>> I've tried to look around in the group for past discussions about this 
>> topic but haven't found any.
>> If this has been already debated , please forgive me and point me to the 
>> right direction.
>>
>> I wonder what do you thing about a feature request to have data bindings 
>> also for defines' parameters.
>>
>
>
> I'm skeptical about their value.  We already have data bindings for 
> classes, by which resource parameters can (indirectly) be injected, and I 
> am inclined to think that classes are the right level of abstraction.  On 
> the other hand, we also have create_resources(), which already can give you 
> resource-level data binding if you want to use it that way.
>
> I do not favor drawing distinctions between defined resource types and 
> native resource types.  On that basis, I would argue for data binding 
> either for all resource types or for none, and against data binding for 
> only defined types.
>
> I am concerned about the impact.  It is already somewhat costly for Puppet 
> to evaluate data bindings for class parameters, and adding bindings for 
> resource parameters (even just for resources of defined types) will magnify 
> that.  Note that the cost scales with the aggregate number of defined 
> parameters for all declared resources, independent whether any data are 
> actually bound.  In fact, the cases were no data are bound are the most 
> costly, because hiera must then search the entire hierarchy.
>

Yes, these are valid and convincing points.
Anyway if we find data binding useful for classes and can bear the 
performance overhead, I suppose we can do the same for defined types.
 

>
>  
>
>> Naming is straightforward, a define like:
>> apache::vhost { 'example.com': }
>>
>> could have its params looked in this namespace:
>> apache::vhost::example.com::<parameter>
>>
>> My poor understanding of Puppet code points me to:
>>
>> https://github.com/puppetlabs/puppet/blob/master/lib/puppet/resource.rb#L343
>> and makes me guess that such a change should not be too difficult.
>>
>
>
> I agree, the change probably would not be difficult to implement -- just 
> costly.  It might be interesting to have some data on what proportion of 
> invocations of that method follow the "return nil" branch, avoiding a 
> lookup.  As a wild guess, I'll say at least 75% in a typical catalog 
> compilation run (maybe we can start a pool :-)).  Even if it were only 25%, 
> though, that would translate into a 33% increase in the number of 
> (expensive) lookups.
>  
>
>> I see many wonderful use cases for such a feature and no apparent cons.
>>
>
>
> I see no particularly good use cases and several cons, but I'm prepared to 
> be amazed by your vision.  Would you care to elaborate?
>

Yes, why not. Let me digress a bit then. It could be useful to verify if 
the following idea seems cool only to me.

First, a premise.
I've written a lot of modules which are ageing and have large parts which 
are very similar. I don't have the time to keep them all updated and there 
are around better alternatives for many applications, even if sometimes 
when I try to use modules from others I find myself screaming in despair.
For a long time I wondered how I could bypass all my code duplication, at 
the same time I was more and more convinced that an application module 
should be considered as a sort of library, to be used as is, without 
modifications, (reusability), which have standard interfaces (naming 
standards) and should not be opinionated in how in manages its application.
According to me opinionated modules can stay at higher abstraction levels 
(profiles/stacks/whatever... they have to deliver a working setup, so some 
choice on how things should be done is needed there) but the component 
modules should just expose a clear and consistent interface on how to 
manage the application they are made for.
Also I've seen that most of the times I found myself just with the need of 
having a configuration file as wanted, eventually managing correlations and 
integrations among (component) modules in custom higher abstraction classes 
with dedicated templates and resources where all the logic could be defined 
as I needed.
Finally I think that exposing as modules parameters each (or many) of the 
managed application configuration entries is a dead end.
When I see a define like 
this: 
https://github.com/puppetlabs/puppetlabs-apache/blob/master/manifests/vhost.pp 
with dozens of application specific parameters and the virtual host file 
content managed with:

    content => template('apache/vhost.conf.erb'),

instead of something like:

define apache::vhost(
    $docroot,
    $template = 'apache/vhost.conf.erb',

[...]

    content => template($template),

I ask me a lot of weird questions. But I'm digressing. My point is that a 
reusable module should allow total freedom on how its configurations should 
be managed: with a file-based approach (source/template/ now 
epp_template...), with a setting-based approach, (augeas, file_line..) with 
concat or whatever. User should decide what's best for him, not the module 
author. 
Also I think that a single parameter that expects an hash ( options_hash, 
config_file_options_hash, options, config... name it as you want) whose key 
values can be freely used in a [custom] template is better than dozens of 
parameters, totally unmaintainable, one for each possible configuration 
entry of an application (and for each one, as you pointed, a data binding 
lookup).

Given this premise (longer than expected, sorry), I've recently thought 
about a single module: tp (stays for tiny puppet) which should be able to 
manage essential features of any application.
Something you can use in manifests in a similar fashion:

To install an application (the tp module contains all the data to do it 
right on different OS) 
  tp::install { 'redis': }  

To configure it via a template:
  tp::conf { 'redis.conf':
    application => 'redis',
    template    => 'site/redis/redis.conf.erb',
  }  

Or, alternatively (using in the title any sane separator):
  tp::conf { 'redis--redis.conf':
    template    => 'site/redis/redis.conf.erb',
  }  

To configure it via the fileserver:
  tp::conf { 'redis.conf':
    application => 'redis',
    source      => 'puppet:///modules/site/redis/redis.conf',
  }  

But also have something like (to manage single lines in a configuration 
file):
  tp::line { 'redis::redis.conf::port':
    value => '1234',
  }  

or even something like:
  tp::concat { 'redis':
     target   => 'redis.conf',
     order    => 10,
     content => 'port 1234',
  }  

And manage, if overrides are needed, any internally used parameter with 
something like:
  tp::settings { 'redis':
    lookup_strategy => 'merge', # Such a settings should define if the 
module's data has to be merged or not with user data
    settings => {
      config_dir_path => '/opt/redis/conf',
      tcp_port        => '3242',
      pid_file_path   => '/opt/redis/run/redis.pid',
    },

Also, it could be nice to have a face that allows commands like:
puppet tp check redis  # To check is redis is running, based on settings 
like service name , pid file, port ... (Incidentally this would make 
integration tests a "bit" easier and quicker)
puppet tp info redis # To show info about how redis is managed by Puppet or 
how it is working

Basically such a tp module would be a sum of most of my existing modules 
main features + the puppi module (https://github.com/example42/puppi,  for 
the functionalities not related to application deployments).

Now, the real added value of such a thing would be a (Hiera like) set of 
yaml files where all the default settings for as many applications as 
possible for different operating systems can be defined in order to make 
usage of the previous defines possible with a wide variety of applications 
and allow, at the same time, extreme customization options.

To do this (hey, this is the topic of this thread), it would have been nice 
to have a data in modules approach (as based on defines parameters) and 
have in files like:
tp/data/redis/default.yaml , tp/data/redis/osfamily/RedHat.yaml all the 
data needed for all the managed applications, such as :
---
  tp::settings::redis::port: '6379'
  tp::settings::redis::config_file_path: '/etc/redis/redis.conf'

Or, alternatively, data expressed in a format like :
---
  redis::packages: (or tp::install::redis::packages...)
    redis:
      ensure: present
      alias: 'redis'

  redis::services:
    redis:
      ensure: running
      enable: true
      alias: 'redis'
      require: Package[redis]

  redis::files:
    '/etc/redis/redis.conf':
      ensure: present
      owner: root
      group: root
      mode: 0644
      alias: 'redis.conf'
      notify: Service[redis]
    '/etc/redis':
      ensure: directory
      owner: root
      group: root
      mode: 0755
      alias: 'redis.dir'
      notify: Service[redis]

In this case the tp::install code could be as simple as this POC:
define tp::install (

  $packages  = { } ,
  $services  = { } ,
  $files     = { } ,
  $execs     = { } ,
  $users     = { } ,

  $configs   = { } ,

  ) {

  if $packages {
    create_resources('package', $packages)
  }

  if $services {
    create_resources('service', $services)
  }

  if $files {
    create_resources('file', $files)
  }

  if $execs {
    create_resources('exec', $execs)
  }

  if $users {
    create_resources('user', $users)
  }

}


Anyway, however is organized the internal data, and the relevant code 
(instead of the create_resource we could use a lambda and cycle over the 
various hashes) having the possibility to use Hiera for the backend would 
be a good thing also because it would make easier for user to override the 
default module data with custom one.

I guess there are better ways to obtain the same (suggestions welcomed) 
rather than enabling  data bindings for defined types  and using data in 
modules (both features being not existing in Puppet core). For example with 
a custom function, but I have to figure out how to do it in the right way.

... but, what were we talking about? :-)

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-dev/11178e96-9a30-4b89-9df9-5c31207ad9ce%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to