In regard to: Re: [Puppet Users] class parameters that depend on other...:
On 2018-06-12 00:55, Tim Mooney wrote:
[snip some of my original context]
Here's an example:
modules/sandbox/manifests/init.pp:
#
# This module exists only to serve as a sandbox where we can
experiment with
# puppet code.
#
class sandbox(
Enum['typeA', 'typeB', 'combined'] $server_type = 'combined',
String $service_name =
$::sandbox::params::service_name,
) inherits ::sandbox::params {
notice("sandbox initialized.\n")
notice("\$server_type = ${server_type}\n")
notice("\$service_name = ${service_name}\n")
}
modules/sandbox/manifests/params.pp:
#
# a 'sandbox' class for the params pattern.
#
class sandbox::params {
$_server_type_actual = $::sandbox::server_type
case $_server_type_actual {
'combined': {
$service_name = 'sandbox-typeA+typeB'
}
'typeA': {
$service_name = 'sandbox-typeA'
}
'typeB': {
$service_name = 'sandbox-typeB'
}
default: {
fail("\n\nsandbox::server_type must be one of: combined,
typeA, typeB\n")
}
}
}
Hopefully the *intent* is relatively clear: provide an intelligent
default
value for $service_name based on what the value is for $server_type, but
allow our "intelligent default" value to be overridden. If
'sandbox::server_type' is set to 'typeB' in our hiera hierarchy, I want
the *default* value for 'sandbox::service_name' to become
'sandbox-typeB'.
If the person configuring the machine needs to override that too, they
should be able to, but setting just the first setting should provide
suitable defaults for the others.
[snip some of my original context]
For starters you do not really need a params.pp or inheritance. Simply
configure all parameters in hiera.
Then, you can produce the default value by calling a function. For
example like this:
function mymodule::default_from_a($x) {
if $x == 'type-A' {
'sandbox-typeA'
}
}
class example($a, $b = mymodule::default_from_a($a)) {
notice $a
notice $b
}
class {example: a => 'type-A' }
Thanks for your response Henrik! The function use is an interesting
approach that I would not have considered. It works well in the simple
example I presented and accomplishes what I was trying to do.
I'm not sure how I would scale this to something that's "real world" in
size, though.
Let's say you had *many* parameters that you wanted to set defaults for
(but allow overrides on an individual basis) based on a single parameter.
In my environment, the best example where we've used this is to support
the alternate versions of particular packages that are available for
RHEL (and respins) using Software Collections Library (SCL).
For example, on RHEL 6, the standard packages provide php 5.3.3 (plus
some backports and vendor "special sauce").
However, there are alternate versions available from SCL:
php54-php
php55-php
rh-php56-php
rh-php70-php
So to support various web application requirements, we have modules
that do stuff like (sorry for the lengthy code):
if $facts['os']['family'] == 'RedHat' {
if $facts['os']['release']['major'] == '5' {
#
# There's no easy httpd 2.4 option for RHEL 5, so barf
#
fail("\n\nRHEL 5 is not supported.\n\n")
} elsif $facts['os']['release']['major'] == '6' {
# PHP-related settings.
$php_variant = hiera('scl::php', 'php54')
if $php_variant == 'php54' or $php_variant == 'php55' {
# don't need to include the fpm package, as the phpfpm class
gets it
$php_extra_packages = hiera('scl::php::extra_packages',
[
"${php_variant}-runtime",
$php_variant,
"${php_variant}-php-cli",
"${php_variant}-php-ldap",
"${php_variant}-php-mbstring",
"${php_variant}-php-pdo",
])
$php_fpm_package_name = "${php_variant}-php-fpm"
$php_fpm_service_name = $php_fpm_package_name
$php_fpm_pool_dir =
"/opt/rh/${php_variant}/root/etc/php-fpm.d"
$php_fpm_pid_file =
"/opt/rh/${php_variant}/root/var/run/php-fpm/php-fpm.pid"
$php_config_dir = "/opt/rh/${php_variant}/root/etc"
} elsif $php_variant != 'UNDEF' {
#
# for version 5.6.x and later, the name may include rh- at the
start
# and many of the paths have changed.
#
# don't need to include the fpm package, as the phpfpm class
gets it
$php_extra_packages = hiera('scl::php::extra_packages',
[
"${php_variant}-runtime",
$php_variant,
"${php_variant}-php-cli",
"${php_variant}-php-ldap",
"${php_variant}-php-mbstring",
"${php_variant}-php-pdo",
])
$php_fpm_package_name = "${php_variant}-php-fpm"
$php_fpm_service_name = $php_fpm_package_name
$php_fpm_pool_dir = "/etc/opt/rh/${php_variant}/php-fpm.d"
$php_fpm_pid_file =
"/var/opt/rh/${php_variant}/run/php-fpm/php-fpm.pid"
$php_config_dir = "/etc/opt/rh/${php_variant}"
}
} else {
# hack to work around no support for true undef in hiera
$php_variant = hiera('scl::php', 'UNDEF')
#
# verify that $php_variant is either UNDEF or matches one of:
#
# php55
# rh-php56
# rh-php70
#
validate_re($php_variant, [
'^UNDEF$',
'^php55$',
'^rh-php56$',
'^rh-php70$'
],
'scl::php must be one of: UNDEF, php55, rh-php56,
rh-php70'
)
if $php_variant == 'UNDEF' {
#
# RHEL 7 or later, with default php from the base operating system
#
# don't need to include the fpm package, as the phpfpm class
gets it
$php_extra_packages = hiera('php::extra_packages',
[
'php-cli',
'php-ldap',
'php-mbstring',
'php-pdo',
])
$php_fpm_package_name = 'php-fpm'
$php_fpm_service_name = $php_fpm_package_name
$php_fpm_pool_dir = '/etc/php-fpm.d'
$php_fpm_pid_file = '/var/run/php-fpm/php-fpm.pid'
$php_config_dir = '/etc'
} elsif $php_variant == 'php55' {
#
# RHEL 7, with SCL php55
#
# don't need to include the fpm package, as the phpfpm class
gets it
$php_extra_packages = hiera('scl::php::extra_packages',
[
"${php_variant}-runtime",
$php_variant,
"${php_variant}-php-cli",
"${php_variant}-php-ldap",
"${php_variant}-php-mbstring",
"${php_variant}-php-pdo",
])
$php_fpm_package_name = "${php_variant}-php-fpm"
$php_fpm_service_name = $php_fpm_package_name
$php_fpm_pool_dir =
"/opt/rh/${php_variant}/root/etc/php-fpm.d"
$php_fpm_pid_file =
"/opt/rh/${php_variant}/root/var/run/php-fpm/php-fpm.pid"
$php_config_dir = "/opt/rh/${php_variant}/root/etc"
} else {
#
# RHEL 7 or later, php from SCL, using the newer naming and layout
# conventions.
#
# don't need to include the fpm package, as the phpfpm class
gets it
$php_extra_packages = hiera('scl::php::extra_packages',
[
"${php_variant}-runtime",
$php_variant,
"${php_variant}-php-cli",
"${php_variant}-php-ldap",
"${php_variant}-php-mbstring",
"${php_variant}-php-pdo",
])
$php_fpm_package_name = "${php_variant}-php-fpm"
$php_fpm_service_name = $php_fpm_package_name
$php_fpm_pool_dir = "/etc/opt/rh/${php_variant}/php-fpm.d"
$php_fpm_pid_file =
"/var/opt/rh/${php_variant}/run/php-fpm/php-fpm.pid"
$php_config_dir = "/etc/opt/rh/${php_variant}"
}
}
} else {
fail("Unsupported osfamily=${$facts['os']['family']}\n")
}
As you can see, there are potentially dozens of settings that depend on
the "big feature switch" of 'scl::php', and we need to be able to override
some or all of the defaults.
While it would be possible to write a function to allow for each and
every one of these to have a dynamic default based on the setting
of scl::php, it's going to be fairly confusing to some of my coworkers
that don't work with puppet as much as I do. Maybe that's just the
trade-off I have to make to support this kind of thing.
Ultimately, I'm trying to modernize some of the now outdated practices
we've adopted in our modules, with an eye toward current best practices.
I don't want to have to keep explaining to our casual puppet users why
our modules look so different from stuff they see when they look at the
docs or examine a module from the forge.