Proposal: Managing Puppet’s configuration data
There are many best practices and standards for module development that need to be identified and agreed upon before modules can be truly reusable.
One of the most urgent needs is a well defined process for configuration data organization and overrides.
Fortunately, progress has already been made towards this goal which I can build upon…
My experiment expands on the work by R.I. Pienaar on extlookup.
Tons of ideas borrowed from conversations I’ve had with Alessandro Franceschi which are outlined in his presentation for Puppetcamp
Goal:
separation of configurable data from puppet manifests:
- puppet manifests – Puppet resources, dependencies, and language elements.
- configurable data – data that could differ between runs of the same manifests.
- facilitates well defined data override structure
- allows users to interact with modules in a well-defined way.
- allows modules to be used without reading/modifying the source code (encapsulation of logic through a well defined interface).
- easier to manage and override platforms where differences can be described as data.
- ie: debian-ish v redhat-ish
- allows finer grain access control.
- ie: some users (devops) have permission to change manifests, while other users (operators) have limited permissions to change configuration data related to a specific environment (ie: production/datacenter1).
Proposed solution:
well defined override precedence:
- modules should be packaged with a data store.
- introduce new module directory <modulename/data/>
- default data can be shipped with modules and stored separately from configuration logic.
- module data store should allow fact/variable based overrides (ie: %{operatingsystem} overrides default, like extlookup}) .
- allow per site data stores that override a module’s data store.
- introduce a single directory that can be used to override configuration.
- </etc/puppet/site-overrides/modulename/data> – overrides should mimic module structure.
- overrides path should be similar to module datastore
- introduce a single directory that can be used to override configuration.
- all data is managed as attributes for parameterized classes
- allows all data to be overridden during class declaration.
version 2.6.x of Puppet actually brings us most of the way towards this solution with the following new features:
- extlookup
- parameterized classes
Example:
I have chosen to implement a simple motd module to demonstrate the proposed data management solution:
Components:
- module layout:
|-- data | |-- CentOS.csv | `-- default.csv |-- manifests | |-- init.pp |-- templates | `-- motd.erb `-- tests |-- init.pp - data override layout
site-overrides/ `-- motd `-- data `-- CentOS.csv - templates/motd.erb
Templates allow an easy way to see the resulting values of variables.DefaultData <%= default_data %> MoreData <%= more_data %> LocalOveride <%= local_override %> OverrideData <%= override_data %>
- manifests/init.pp
- simple class that specifies all data as class attributes:
- all data defaults to the value derived from extlookup
- all data can be overriden when class is declared.
class motd ( $default_data = extlookup('default_data'), $more_data = extlookup('more_data'), $override_data = extlookup('override_data'), $local_override = extlookup('local_override') ){ file { '/etc/motd': content => template('motd/motd.erb'), } } - tests/init.pp
- specify lookup precedence for extlookup
- declare class and specify highest precedence overrides.
$extlookup_datadir = '/' $local_overrides = '/etc/puppet/site' $extlookup_precedence = [ "${local_overrides}/%{module_name}/data/%{operatingsystem}", "${local_overrides}/%{module_name}/data/default", "%{module_data_dir}/%{operatingsystem}", "%{module_data_dir}/default" ] class { 'motd': override_data => 'override' }
precedence of data lookup
- default to extlookup value: use specified precendence
- /etc/puppet/modules/motd/data/default
default_data, default local_override, default
- /etc/puppet/modules/motd/data/CentOS
more_data, centos override_data, centos
- /etc/puppet/site-overrides/motd/data/default
- /etc/puppet/site-overrides/motd/data/CentOS
local_override, local_centos
- /etc/puppet/modules/motd/data/default
- class parameters override everything
class { 'motd': override_data => 'override' }
Results
:
#>puppet apply tests/init.pp #>cat /etc/motd DefaultData default MoreData centos LocalOveride local_centos OverrideData override
Changes to Puppet:
This example required the following changes to Puppet core:
- patch to extlookup
- allow multiple puppet variables to be interpolated.
- patch to puppet (Puppet::Resource::Type)
- create magic variable in Puppet::Resource::Type that can find the current manifest’s module’s data dir – module_data_dir
- move the code where magic variables(module_name, module_data_dir) are added to a classes scope so they will be available before parameter defaults are evaluated.
branch of code from 2.6.3rc1 at:
http://github.com/bodepd/puppet/tree/data-hack
This code requires more significant changes to puppet:
- external node classifier interface needs to support parameterized classes.
Improvements:
- puppet.conf (and environments) should support an option for the following:
- site_override_dir – directory where local override modules are found.
- default – /etc/puppet/site-overrides/
- lookup_precendence – order expressing how files are looked up
- default-%{operatingsystem}:default
- site_override_dir – directory where local override modules are found.
Additional requirements:
Ability to resolve data from a class.
- A modules configuration needs to be readable by other modules.