Alternative puppet hiera connector. Design goals:
- Complete configuration in hiera
- Only one default node in puppet manifest
- Configuration of classes and resources
- Support for deeper merging of class arguments
Configuration are structured via "hiera modules".
Hiera modules are absolute independent from puppet modules. Often there is a one to one relationship between a hiera module a puppet module because the hiera module is used to configure the puppet module. But hiera modules without a corresponding puppet module or multiple hiera modules for one puppet module are also common. For example we have a mysqlserver hiera module and a mysqlclient hiera module which both configure the mysql puppet module.
Hiera lookups take the following form:
[modulename::[modulearea::]]type[::option]
At the moment the following hiera lookup types are defined:
- require
- resources
- defaults
- default_subresources
- default_mapping
- collection
The term resource is used for all kind of resources, including classes.
In all examples the yaml backend is used for easy readability. But all other hiera backends also work. As long as they support deeper merging.
The merge behavior deeper is used.
Hiera modules are used to load all needed resources for a note.
Default loading procedure of resources:
- Determine which hiera modules should be loaded, by calling hiera_array('modules') and store them in unloadedmodules
- Try to load the first hiera module in unloadedmodules
- Set ::hiera_module to loading hiera module name
- Check if loading hiera module requires other unloaded hiera modules, by calling hiera_array("#{module.name}::require") and filter already loaded hiera modules
- If at least one unloaded module is required, prepend the unloaded hiera modules to unloadedmodules, unset ::hiera_module goto 1
- Load resources by calling hiera_hash("#{module.name}::resources")
- If resource class exists, load classes in order of definition with class_params
- For each resource type load the defined resources
- Mark hiera module loaded, unset ::hiera_module, goto 2
hiera hierachy:
- node/%{::clientcert}
- role/%{::role}
- modules/%{::hiera_module}
- global
default node configuration:
# if an enc is used, role can be provided by the enc:
$role = hiera_function('role', 'unknownrole')
node default {
$modules = load_hiera_modules()
}
yaml configuration files:
node/web01.example.com.yaml
role: webserver
role/webserver.yaml
modules:
- standard
- webserver
- apache
apache::resources:
class_params:
'apache':
keepalive: false
serveradmin: '[email protected]'
apache::vhosts:
'www.example.com'
servername: 'www.example.com'
docroot: '/var/www/exmaple.com'
webserver::resources:
file:
'motd':
path: '/etc/motd'
content: "I'm a webserver."
modules/standard.yaml
require:
- ntp
[...]
modules/ntp.yaml
ntp::resources:
class:
- ntp
class_params:
'ntp':
servers:
- 'ntp1.example.com iburst'
- 'ntp2.example.com iburst'
modules/apache.yaml
apache::resources:
class:
- apache
class_params:
'apache'
purge_configs: true
default_vhost: false
serveradmin: '[email protected]'
mpm_module: 'prefork'
Virtual and exported resources can be defined as in puppet. Prefix one @ for virtual resources and two @@ for exported resources to the resource type.
Realizing the virtual and exported resources is done by collections as in puppet described later.
Define a virtual user:
modules/users.yaml
users::resources:
@user:
'luke':
uid: 1000
Define to export sshkey resource:
modules/standard.yaml
standard::resources:
@@sshkey:
%{::fqdn}:
type: 'ssh-rsa'
key: %{::sshrsakey}
Areas work like case statements, loading resources only if the case matches. Every hiera module can define as many areas as they wish. The defined areas of one hiera module are complete independent of areas of other hiera modules.
Extending the apache hiera module with two areas:
- osf_%{::osfamily} for some os specific resources
- monitoring_%{::monitoring} for some resources depending on the used monitoring system
modules/apache.yaml
apache::areas:
- 'osf_%{::osfamily}'
- 'monitoring_%{::monitoring}'
apache::resources:
class:
- apache
class_params:
'apache'
purge_configs: true
default_vhost: false
serveradmin: '[email protected]'
mpm_module: 'prefork'
apache::area_osf_Debian::resources:
file:
'/etc/apache2/conf.d/additional.conf':
ensure: present
owner: 'root'
content: |
BrowserMatch "check\_http" dontlog
apache::area_osf_Redhat::resources:
file:
'/etc/httpd/conf.d/additional.conf':
ensure: present
owner: 'root'
content: |
BrowserMatch "check\_http" dontlog
apache::area_monitoring_nrpe::require:
- nrpe
apache::area_monitoring_nrpe::resources:
package:
perl:
ensure: present
nrpe::plugin:
'apache_procs':
check_command: 'check_procs'
command_args: "--ereg-argument-array='^/usr/sbin/apache2' -w 4:200 -c 2:250"
'apache_status':
check_command: 'check_apapche_status'
command_args: '-H localhost'
modules/nrpe.yaml
nrpe::resources:
class:
- nrpe
class_params:
'nrpe':
allowed_hosts: 'mon.example.com'
nrpe::plugin:
'load':
check_command: 'check_load'
command_args: '-w 4,3,2 -c 5,4,3'
Default values can be set for every resource type expect classes. They will be added as default values to the create resources call, so they only work for in hiera defined resources and not for resources created by loaded classes etc. It's possible to set default values at different levels:
- Global for all modules
- Local for a specific module
- Local for a specific module area
If at different level default values for the same resource type are defined, then they get merged with priority to the most specialized definition.
Globally define that all files created by the file resource are owned by root if nothing other is configured:
global.yaml
defaults::file:
owner: root
group: root
Collections are used to realize virtual or exported resources. This should be handled in puppet modules in my opinion, but as we don't live in a perfect world with only perfect puppet modules, it can be sometimes necessary to realize resources in the node configuration.
Realize all exported sshkey resources:
modules/standard.yaml
standard::collection:
sshkey:
type: exported
query: ''
Realize all virtual resources with tag admin:
role/webserver.yaml
standard::collection:
user:
type: virtual
query: 'tag == "admin"'
Subresources are resources that depend on another "parent" resource. A subresource gets automatically added a requirement to the parent resource.
Parent resource user and adding a subresource ssh_authorized_key.
modules/user.yaml
user::resources:
'doe':
comment: 'John Doe'
ensure: present
uid: 1000
subresources:
ssh_authorized_key:
key1:
type: 'ssh-rsa'
key: 'AAA[..]=='
adminusers::default_mapping::from_user_to_ssh_authorized_key:
title:
user:
target: '/etc/ssh/authorized_key/&{title}'
ensure: 'ensure'
By default only the ensure attribute is mapped from the parent resource to the subresource. But it is possible to map other attributes as well vie the default_mapping key. It is possible to map a attribute of the parent resource to multiple attributes in the subresource. Also values can be transformed as show above. There are some limitations which attributes can be mapped from parent to subresources:
- Only in hiera defined attributes can be mapped. Default values set by the resource can't because they aren't known at the time the mapping take place.
- It isn't possible to transform values of the subresource
- The mapped parent values are added as default values at creation to the subresource, so isn't possible to override them by explicitly setting them in the subresource
Default subresources are resources that get added as subresource to a certain resource type by default.
By default bless every user with the one true editor:
adminusers::defaultsubresources::user:
hiera::file:
'inputrc':
path: '.inputrc'
mode: 0644
content: |
set editing-mode vi