Using the future parser
Puppet language is evolving at the moment; many features that are expected to be included in the next major release (4) are available if you enable the future parser.
Getting ready
- Ensure that the
rgen
gem is installed. - Set
parser = future
in the[main]
section of yourpuppet.conf
(/etc/puppet/puppet.conf
for open source Puppet asroot,/etc/puppetlabs/puppet/puppet.conf
for PuppetEnterprise, and~/.puppet/puppet.conf
for a non-root user running puppet). - To temporarily test with the future parser, use
--parser=future
on the command line.
How to do it...
Many of the experimental features deal with how code is evaluated, for example, in an earlier example we compared the value of the $::facterversion
fact with a number, but the value is treated as a string so the code fails to compile. Using the future parser, the value is converted and no error is reported as shown in the following command line output:
t@cookbook:~/.puppet/manifests$ puppet apply --parser=future version.pp Notice: Compiled catalog for cookbook.example.com in environment production in 0.36 seconds Notice: Finished catalog run in 0.03 seconds
Appending to and concatenating arrays
You can concatenate arrays with the +
operator or append them with the <<
operator. In the following example, we use the ternary operator to assign a specific package name to the $apache
variable. We then append that value to an array using the <<
operator:
$apache = $::osfamily ? { 'Debian' => 'apache2', 'RedHat' => 'httpd' } $packages = ['memcached'] << $apache package {$packages: ensure => installed}
If we have two arrays, we can use the +
operator to concatenate the two arrays. In this example, we define an array of system administrators ($sysadmins
) and another array of application owners ($appowners
). We can then concatenate the array and use it as an argument to our allowed users:
$sysadmins = [ 'thomas','john','josko' ] $appowners = [ 'mike', 'patty', 'erin' ] $users = $sysadmins + $appowners notice ($users)
When we apply this manifest, we see that the two arrays have been joined as shown in the following command line output:
t@cookbook:~/.puppet/manifests$ puppet apply --parser=future concat.pp Notice: [thomas, john, josko, mike, patty, erin] Notice: Compiled catalog for cookbook.example.com in environment production in 0.36 seconds Notice: Finished catalog run in 0.03 seconds Merging Hashes
If we have two hashes, we can merge them using the same +
operator we used for arrays. Consider our $interfaces
hash from a previous example; we can add another interface to the hash:
$iface = { 'name' => 'eth0', 'ip' => '192.168.0.1', 'mac' => '52:54:00:4a:60:07' } + {'route' => '192.168.0.254'} notice ($iface)
When we apply this manifest, we see that the route attribute has been merged into the hash (your results may differ, the order in which the hash prints is unpredictable), as follows:
t@cookbook:~/.puppet/manifests$ puppet apply --parser=future hash2.pp Notice: {route => 192.168.0.254, name => eth0, ip => 192.168.0.1, mac => 52:54:00:4a:60:07} Notice: Compiled catalog for cookbook.example.com in environment production in 0.36 seconds Notice: Finished catalog run in 0.03 seconds
Lambda functions
Lambda functions are iterators applied to arrays or hashes. You iterate through the array or hash and apply an iterator function such as each
, map
, filter
, reduce
, or slice
to each element of the array or key of the hash. Some of the lambda functions return a calculated array or value; others such as each
only return the input array or hash.
Lambda functions such as map
and reduce
use temporary variables that are thrown away after the lambda has finished. Use of lambda functions is something best shown by example. In the next few sections, we will show an example usage of each of the lambda functions.
Reduce
Reduce is used to reduce the array to a single value. This can be used to calculate the maximum or minimum of the array, or in this case, the sum of the elements of the array:
$count = [1,2,3,4,5] $sum = reduce($count) | $total, $i | { $total + $i } notice("Sum is $sum")
This preceding code will compute the sum of the $count
array and store it in the $sum
variable, as follows:
t@cookbook:~/.puppet/manifests$ puppet apply --parser future lambda.pp Notice: Sum is 15 Notice: Compiled catalog for cookbook.example.com in environment production in 0.36 seconds Notice: Finished catalog run in 0.03 seconds
Filter
Filter is used to filter the array or hash based upon a test within the lambda function. For instance to filter our $count
array as follows:
$filter = filter ($count) | $i | { $i > 3 } notice("Filtered array is $filter")
When we apply this manifest, we see that only elements 4 and 5 are in the result:
Notice: Filtered array is [4, 5]
Map
Map is used to apply a function to each element of the array. For instance, if we wanted (for some unknown reason) to compute the square of all the elements of the array, we would use map
as follows:
$map = map ($count) | $i | { $i * $i } notice("Square of array is $map")
The result of applying this manifest is a new array with every element of the original array squared (multiplied by itself), as shown in the following command line output:
Notice: Square of array is [1, 4, 9, 16, 25]
Slice
Slice is useful when you have related values stored in the same array in a sequential order. For instance, if we had the destination and port information for a firewall in an array, we could split them up into pairs and perform operations on those pairs:
$firewall_rules = ['192.168.0.1','80','192.168.0.10','443'] slice ($firewall_rules,2) |$ip, $port| { notice("Allow $ip on $port") }
When applied, this manifest will produce the following notices:
Notice: Allow 192.168.0.1 on 80 Notice: Allow 192.168.0.10 on 443
To make this a useful example, create a new firewall resource within the block of the slice instead of notice:
slice ($firewall_rules,2) |$ip, $port| { firewall {"$port from $ip": dport => $port, source => "$ip", action => 'accept', } }
Each
Each is used to iterate over the elements of the array but lacks the ability to capture the results like the other functions. Each is the simplest case where you simply wish to do something with each element of the array, as shown in the following code snippet:
each ($count) |$c| { notice($c) }
As expected, this executes the notice
for each element of the $count
array, as follows:
Notice: 1 Notice: 2 Notice: 3 Notice: 4 Notice: 5
Other features
There are other new features of Puppet language available when using the future parser. Some increase readability or compactness of code. For more information, refer to the documentation on puppetlabs website at http://docs.puppetlabs.com/puppet/latest/reference/experiments_future.html.