Reputation: 8896
Basically, I find myself making the same long class declaration every time:
node 'gluster3redis097.myservice.com' {
class { 'redis' :
class {'invoke' : }
class {'users' : }
class {'redis' :
package_ensure => '3.0.5',
#extra_config_file => '/etc/redis.d/redis-gluster3-master.conf',
daemonize => 'yes',
pid_file => '/var/run/redis.pid',
log_level => 'notice',
log_file => '/var/log/redis/redis.log',
#save_db_to_disk => false,
workdir => './',
bind => $::ipaddress,
slaveof => "${$gluster3redis_master_ips[37]}:6379",
slave_serve_stale_data => true,
# 2015.12.01 nathan Do not allow inadvertent writes to the slave
slave_read_only => true,
repl-diskless-sync-delay => '5',
repl-ping-slave-period => '10',
... and so on ...
... and so forth ...
Let us suppose, for this cluster, every FIFTH node has a separate master.
So, guess the only part that changes?
slaveof => "${$gluster3redis_master_ips[37]}:6379",
There has to be a better way.
-- Pocahontas (1995)1
According to https://docs.puppetlabs.com/puppet/latest/reference/lang_node_definitions.html#multiple-names, it's a bad idea to use the Puppet inherits
keyword.
Plus, to my dismay, in https://docs.puppetlabs.com/puppet/latest/reference/lang_node_definitions.html#aside-best-practices , they describe the following best practices:
Aside: Best Practices
Although node statements can contain almost any Puppet code, we recommend that you only use them to set variables and declare classes. Avoid using resource declarations, collectors, conditional statements, chaining relationships, and functions in them; all of these belong in classes or defined types. This will make it easier to switch between node definitions and an ENC.2
Could I define a custom type?
I read through How to pass node specific information to class in puppet? , but I'm not sure he's asking the same thing that I am, and although I'm perfectly willing to learn how to define types, I'm not familiar with them enough to decide whether to go that route.
How the blazes do I avoid repeating myself with every Puppet Node definition like this for this Redis cluster?
I would welcome even a very generic answer that I could apply to my particular case, which I have also generalized.
UPDATE: Applying a common configuration using Hiera by a common.yaml file for this set of environments seems to have worked. I will elaborate further in an answer, if Dan Bowling does not volunteer one.
Upvotes: 2
Views: 158
Reputation: 1225
Here's a more flushed out answer for the comment I initially placed:
Any time you find yourself re-declaring settings as class parameters, Hiera should be considered. From the docs:
Hiera is a key/value lookup tool for configuration data, built to make Puppet better and let you set node-specific data without repeating yourself.
Your first step is to identify a hierarchy, since Hiera will use that hierarchy to look up an appropriate value for the requested key. In your example, a simple hierarchy is all that is needed. Here's an example hiera.yaml
configuration file:
:backends:
- yaml
:hierarchy:
- "node/%{::hostname}"
- "common"
:yaml:
:datadir: '/your/hiera/data/directory'
:merge_behavior: deeper
About the above config:
/your/hiera/data/directory/node/nodehostname.yaml
for a value first. This is where you can define per-host configurations.common.yaml
in /your/hiera/data/directory/node/common.yaml
So, your common.yaml
might look like this:
redis::package_ensure: '3.0.5'
redis::pid_file: '/var/run/redis.pid'
And you will have node{1,2} with this /your/hiera/data/directory/node/node{1,2}.yaml
:
redis::slaveof: 'your redis master value'
And node{3,4} would have this /your/hiera/data/directory/node/node{3,4}.yaml
:
redis::slaveof: 'your other redis master value'
The :merge_behavior: deeper
in hiera.yaml
is useful if you want to merge settings at different hierarchy levels or combine complex hashes into single values. For more info, see Hiera Lookup Types.
Upvotes: 2