Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Puppet 5 Cookbook

You're reading from   Puppet 5 Cookbook Jump start your Puppet 5.x deployment using engaging and practical recipes

Arrow left icon
Product type Paperback
Published in Jun 2018
Publisher Packt
ISBN-13 9781788622448
Length 394 pages
Edition 4th Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Thomas Uphill Thomas Uphill
Author Profile Icon Thomas Uphill
Thomas Uphill
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Puppet Language and Style FREE CHAPTER 2. Puppet Infrastructure 3. Writing Better Manifests 4. Working with Files and Packages 5. Users and Virtual Resources 6. Managing Resources and Files 7. Managing Applications 8. Servers and Cloud Infrastructure 9. External Tools and the Puppet Ecosystem 10. Monitoring, Reporting, and Troubleshooting 11. Other Books You May Enjoy

Puppet 4/5 changes

The following changes occured in Puppet 4 and carried forward to Puppet 5.

Appending to and concatenating arrays

You can conca/home/test/puppet-beginners-guide-3/tenate 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 apply concat.pp
Notice: Scope(Class[main]): [thomas, john, josko, mike, patty, erin]

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 apply merge.pp
Notice: Scope(Class[main]): {name => eth0, ip => 192.168.0.1, mac => 52:54:00:4a:60:07, route => 192.168.0.254}

Using the sensitive type

It is often the case that you wish to store passwords or other credentials in Puppet. There are a few ways to do so with some level of security, such as eyaml or GPG. However, the unencrypted data may still be leaked via reports and logs. Starting in Puppet 4.6, a new sensitive type was created to address this problem. Data that is stored in a Sensitive type will not be leaked via reports or logs; when the value needs to be recorded it will be replaced with value redacted.

In the following example, we can see how we can output a password to a file but take advantage of the protections of the Sensitive type:

$secret = Sensitive('My Top Secret Password')
file {'/tmp/passwd':
content => "${secret.unwrap}\n",
}
notice($secret)

When we use puppet apply on this code, we see that the notice has the value redacted while the unwrapped value is stored in the file:

t@cookbook:~$ puppet apply sensitive.pp
Notice: Scope(Class[main]): Sensitive [value redacted]
Notice: Compiled catalog for cookbook.example.com in environment production in 0.01 seconds
Notice: /Stage[main]/Main/File[/tmp/passwd]/content: content changed '{md5}6d814ec03401f7954ed41306e8848a07' to '{md5}a4ca22adedac7912cbb7e53ccfba0a9d'
Notice: Applied catalog in 0.03 seconds
t@cookbook:~$ cat /tmp/passwd
My Top Secret Password

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 apply reduce.pp
Notice: Scope(Class[main]): Sum is 15

filter

filter is used to filter the array or hash based on a test within the lambda function. For instance, we filter our $count array as follows:

$count = [1,2,3,4,5]
$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:

t@cookbook:~$ puppet apply filter.pp
Notice: Scope(Class[main]): 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:

$count = [1,2,3,4,5]
$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:

t@cookbook:~$ puppet apply map.pp
Notice: Scope(Class[main]): 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:

t@cookbook:~$ puppet apply slice.pp
Notice: Scope(Class[main]): Allow 192.168.0.1 on 80
Notice: Scope(Class[main]): 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:

$firewall_rules = ['192.168.0.1','80',
'192.168.0.10','443']
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:

t@cookbook:~$ puppet apply each.pp
Notice: Scope(Class[main]): 1
Notice: Scope(Class[main]): 2

Functions in Puppet language

Starting from Puppet 4, you can write functions in the Puppet language instead of Ruby. It is believed at some point that Puppet will move away from using Ruby in the backend, so any new functions you write should use the Puppet language if possible. The interesting thing about writing functions in the Puppet language is that there is no return statement; Puppet will return the last expression from a function as the return value. It is still possible to do more advanced programming while remaining within Puppet language. In the following example, we will use a rough estimation algorithm to calculate the square root of a number.

The first function is used to determine if we are close to the square root:

function close(Integer $number, Float $guess) {
if abs(($guess * $guess) - $number ) < 0.01 {
true
} else {
guessAgain($number,$guess)
}
}

This will either return true if $guess2 is within 0.01 of $number or it will use the next guessAgain function to return the next guess to the main function:

function guessAgain($number, $guess) {
($guess + ($number / $guess )) / 2.0
}

This function is used to make a correction to the current guess, to bring the estimation closer to the square root. The last function is where we do our recursion; recursion is where a function uses itself as part of the algorithm:

function sqrt_($number, $guess) {
if close($number,$guess) == true {
$guess
} else {
sqrt_($number, guessAgain($number, $guess))
}
}
If you are unfamiliar with recursion, I suggest the Wikipedia article on recursion (https://en.wikipedia.org/wiki/Recursion_(computer_science)).

In this function, if the close function returns true, we know we are close enough to the root and can return $guess to the calling function. If not, we call sqrt_ again with a new guess. The final function is just a wrapper of sqrt_ and is used so the caller need not set an initial guess:

function sqrt($number) {
sqrt_($number,1.0)
}

To see this in action, we'll need to call our sqrt function and use notify to print the values returned:

function sqrt_($number, $guess) {
if close($number,$guess) == true {
$guess
} else {
sqrt_($number, guessAgain($number, $guess))
}
}

Now when we run Puppet, we see the following output:

Notice: sqrt(4) = 2.000609756097561
Notice: sqrt(2) = 1.4166666666666665
Notice: sqrt(81) = 9.000011298790216
You have been reading a chapter from
Puppet 5 Cookbook - Fourth Edition
Published in: Jun 2018
Publisher: Packt
ISBN-13: 9781788622448
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image