41,99 €
A Guide to managing servers and automation
This book targets experienced IT professionals and new Puppet uses, who will learn all they need to know to go from installation to advanced automation. Get a rapid introduction to the essential topics and learn how to build best practices for advanced automation with Puppet.
Puppet is a configuration management tool that allows you to automate all your IT configurations, giving you control over what you do to each Puppet Agent in a network, and when and how you do it. In this age of digital delivery and ubiquitous Internet presence, it's becoming increasingly important to implement scaleable and portable solutions, not only in terms of software, but also the system that runs it.
This book gets you started quickly with Puppet and its tools in the right way. It highlights improvements in Puppet and provides solutions for upgrading. It starts with a quick introduction to Puppet in order to quickly get your IT automation platform in place. Then you learn about the Puppet Agent and its installation and configuration along with Puppet Server and its scaling options. The book adopts an innovative structure and approach, and Puppet is explained with flexible use cases that empower you to manage complex infrastructures easily.
Finally, the book will take readers through Puppet and its companion tools such as Facter, Hiera, and R10k and how to make use of tool chains.
This book aims to impart all the knowledge required to tap into not only the basics of Puppet, but also its core. The basic ideas and principles of Puppet-based designs are explored and explained. Sophisticated tools are presented to enable you to use Puppet efficiently and productively.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 319
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: November 2014
Second edition: December 2015
Third edition: September 2017
Production reference: 1080917
ISBN 978-1-78728-471-5
www.packtpub.com
Authors
Martin Alfke
Felix Frank
Copy Editor
Safis Editing
Reviewer
Thomas Dao
Project Coordinator
Kinjal Bari
Commissioning Editor
Pratik Shah
Proofreader
Safis Editing
Acquisition Editor
Chandan Kumar
Indexer
Pratik Shirodkar
Content Development Editor
Mamata Walkar
Graphics
Kirk D'Penha
Technical Editor
Varsha Shivhare
Production Coordinator
Shantanu Zagade
Martin Alfke is the co-founder and CEO of example42 GmbH. He has been a Puppet and automation enthusiast since 2007 and has delivered official Puppet training in Germany since 2011. In the past, he would have said that he is a system administrator. Nowadays, he prefers the term infrastructure engineer. The big difference is that system administrators ssh into systems, whereas infrastructure engineers fix their automation. With example42 GmbH, Martin supports Puppet Inc as a Puppet service delivery partner. He likes giving talks and workshops at conferences around the globe.
Felix Frank has used and programmed computers for most of his life. During and after working on his computer science diploma, he gained experience on the job as a systems administrator, server operator, and open source software developer. He spent six years of his eleven year career as a Puppet power user. In parallel, he spent about two years intensifying his studies through ongoing source code contributions and active participation in several conferences.
Thomas Dao has worn many hats in IT, from Unix administration, build/release engineering, DevOps engineering, Android development, and now, dad to his bundle of joy, Carina. He also enjoys being an organizer of the Eastside Android Developers GDG meetup group. He can be reached at [email protected].
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
Writing Your First Manifests
Getting started
Introducing resources, parameters, and properties
Interpreting output of the puppet apply command
Dry testing your manifest
Using variables
Variable types
Data types
Adding control structures in manifests
Controlling the order of execution
Declaring dependencies
Error propagation
Avoiding circular dependencies
Implementing resource interaction
Examining Puppet core resource types
The user and group types
The exec resource type
The cron resource type
The mount resource type
Summary
Puppet Server and Agents
The Puppet server
Setting up the server machine
Creating the master manifest
Inspecting the configuration settings
Setting up the Puppet agent
The agent's life cycle
Renewing an agent's certificate
Running the agent from cron
Performance optimizations
Tuning puppetserver
Completing the stack with PuppetDB
The Puppet CA
Summary
A Peek into the Ruby Part of Puppet - Facts, Types, and Providers
Putting it all together - collecting system information with Facter
Accessing and using fact values
Extending Facter with custom facts
Simplifying things using external facts
Goals of Facter
Understanding the type system
The resource type's life cycle on the agent side
Command execution control with providers
Resource types with generic providers
Summarizing types and providers
Putting it all together
Summary
Combining Resources in Classes and Defined Types
Introducing classes and defined types
Defining and declaring classes
Creating and using defined types
Understanding and leveraging the differences
Design patterns
Writing comprehensive classes
Writing component classes
Using defined types as resource wrappers
Using defined types as resource multiplexers
Using defined types as macros
Exploiting array values using defined types
Using iterator functions
Including classes from defined types
Ordering and events among classes
Passing events between classes and defined types
Ordering containers
Limitations
The performance implications of container relationships
Mitigating the limitations
The anchor pattern
The contain function
Making classes more flexible through parameters
The caveats of parameterized classes
Preferring the include keyword
Summary
Combining Classes, Configuration Files, and Extensions into Modules
The contents of Puppet's modules
Parts of a module
Module structure
Documentation in modules
Managing environments
Configuring environment locations
Obtaining and installing modules
Module best practices
Putting everything in modules
Avoiding generalization
Testing your modules
Safe testing with environments
Building a component module
Naming your module
Making your module available to Puppet
Implementing basic module functionality
Creating utilities for derived manifests
Adding configuration items
Allowing customization
Removing unwanted configuration items
Dealing with complexity
Enhancing the agent through plugins
Replacing a defined type with a native type
Naming your type
Creating the resource type's interface
Designing sensible parameter hooks
Using resource names
Adding a provider
Declaring management commands
Implementing the basic functionality
Allowing the provider to prefetch existing resources
Making the type robust during provisioning
Enhancing Puppet's system knowledge through facts
Refining the interface of your module through custom functions
Making your module portable across platforms
Finding helpful Forge modules
Identifying module characteristics
Summary
The Puppet Beginners Advanced Parts
Building dynamic configuration files
Learning the template syntax
Using templates in practice
Avoiding performance bottlenecks from templates
Managing file snippets
Single entry in a section
Building from multiple snippets
Using virtual resources
Realizing resources more flexibly using collectors
Cross-node configuration with exported resources
Exporting and collecting resources
Configuring the master to store exported resources
Exporting SSH host keys
Managing hosts files locally
Automating custom configuration items
Simplifying the configuration of Nagios
Maintaining your central firewall
Removing obsolete exports
Setting defaults for resource parameters
Saving redundancy using resource defaults
Avoiding antipatterns
Summary
New Features from Puppet 4 and 5
Upgrading to Puppet 4
Using Puppet 3.8 and environment directories
The Puppet 4 and 5 master
Updating the Puppet agent
Testing Puppet DSL code
Using the type system
Learning lambdas and functions
Creating Puppet 4 functions
Leveraging the new template engine
Handling multiline with HEREDOC
Using Puppet 5 server metrics
Breaking old practices
Converting node inheritance
Dealing with bool algebra on Strings
Using strict variable naming
Learning the new reference syntax
Cleaning hyphens in names
No Ruby DSL anymore
Relative class name resolution
Dealing with different data types
Summary
Separation of Code and Data with Hiera
Understanding the need for separate data storage
Consequences of defining data in the manifest
Building hierarchical data structures
Configuring Hiera
Storing Hiera data
Choosing your backends
Fetching data from classes
Working with simple values
Binding class parameter values automatically
Handling hashes and arrays
Choosing between manifest and Hiera designs
Debugging data lookups
Managing resources from data
Hiera version 5
Summary
Puppet Roles and Profiles
Technical component modules
Implementing components in profiles
The business use case and node classification
Building roles from profiles
Placing code on the Puppet server
The Puppet control repository
Synchronizing upstream modules
R10K code deployment
Summary
Puppet is a configuration management tool that allows you to automate all your IT configurations, giving you control over what you do with each Puppet agent in a network, and when and how you do it. In this age of digital delivery and ubiquitous internet presence, it's becoming increasingly important to implement scalable and portable solutions, not only in terms of software but also the system that runs it.
This book aims to impart knowledge required to tap into not only the basics of Puppet, but also its core. The very basic ideas and principles of Puppet-based designs are explored and explained in this book. A sophisticated tool is presented to enable efficient and productive use.
Chapter 1, Writing Your First Manifests, explains Puppet declarative configuration management based on resources and how to implement them.
Chapter 2, Puppet Server and Agents, covers installation and configuration of Puppet Server, and how to comment agents to the server.
Chapter 3, A Peek into the Ruby Part of Puppet - Facts, Types, and Providers, explains the underlying functions of Facter and its facts, types, and providers in Puppet.
Chapter 4, Combining Resources in Classes and Defined Types, covers self-defined resources that allow you to simplify a repetitive code.
Chapter 5, Combining Classes, Configuration Files, and Extensions into Modules, explains the concepts of Puppet environments and node classification.
Chapter 6, The Puppet Beginners Advanced Parts, covers the Puppet features that offer readability, flexibility, and improvements such as EPP templates, virtual and exported resources, and resource defaults.
Chapter 7, New Features from Puppet 4 and 5, explains the concept of Puppet environments and node classification.
Chapter 8, Separation of Code and Data with Hiera, covers a Puppet way of separating code and data, so data can be managed.
Chapter 9, Puppet Roles and Profiles, provides a workflow that allows separate upgrades of upstream modules and local Puppet implementations.
You need Debian 8+ or Ubuntu 14+, and physical/virtual x86.
This book is meant for an experienced IT professionals and new Puppet users. This book will provide you with all you need to know to go from installation to advanced automation. Get a rapid introduction to the essential topics and learn how to build best practices for advanced automation with Puppet.
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply email [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files emailed directly to you. You can download the code files by following these steps:
Log in or register to our website using your email address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Puppet-Essentials-Third-Edition. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from http://www.packtpub.com/sites/default/files/downloads/PuppetEssentialsThirdEdition_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
Configuration management has become essential to the IT world. Faster development using agile methods has a huge impact on IT operations that need to keep pace with the faster deployment of systems. Server operations in general are hardly even feasible without a robust management infrastructure. Among the available tools, Puppet has established itself as one of the most popular and widespread solutions. Originally written by Luke Kanies, the tool is now distributed under the terms of Apache License 2.0 and maintained by Luke's company, Puppet Inc. It boasts a large and bustling community, rich APIs for plugins and supporting tools, outstanding online documentation, and a great security model based on SSL authentication.
Like all configuration management systems, Puppet allows you to maintain a central repository of infrastructure definitions, along with a toolchain to enforce the desired state on the systems under management. The whole feature set is quite impressive. This book will guide you through some steps to quickly grasp the most important aspects and principles of Puppet.
In this chapter, we will cover the following topics:
Getting started
Introducing resources, parameters, and properties
Interpreting the output of the
puppet apply
command
Using variables
Adding control structures in manifests
Controlling the order of execution
Implementing resource interaction
Examining Puppet core resource types
Installing Puppet is easy. On large Linux distributions, you can just install the Puppet package via apt-get or yum.
The installation of Puppet can be done in the following ways:
From default operating system repositories
From Puppet Inc
The former way is generally simpler. Chapter 2, Puppet Server and Agents, provides simple instructions to install the Puppet Inc packages. A platform-independent way to install Puppet is to get the puppet Ruby gem. This is fine for testing and managing single systems, but it is not recommended for production use.
After installing Puppet, you can use it right away. Puppet is driven by manifests, the equivalent of scripts or programs, written in Puppet's Domain-Specific Language (DSL). Let's start with the obligatory Hello, world! manifest:
# hello_world.ppnotify { 'Hello, world!':}
To put the manifest to work, use the following command (we avoided the term execute on purpose-manifests cannot be executed; more details will follow around the middle of this chapter):
root@puppetmaster:~# puppet apply hello_world.pp
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.45 seconds
Notice: Hello, world!
Notice: /Stage[main]/Main/Notify[Hello, world!]/message: defined 'message' as 'Hello, world!'
Notice: Applied catalog in 0.03 seconds
Before we take a look at the structure of the manifest and the output from the puppet apply command, let's do something useful, just as an example. Puppet comes with its own background service. Let's assume that you want to learn the basics before letting it mess with your system. You can write a manifest to have Puppet make sure that the service is not currently running and will not be started at system boot:
# puppet_service.ppservice { 'puppet': ensure => 'stopped', enable => false,}
To control system processes, boot options, software installation, and the same as the Puppet needs to be run with root privileges. This is the most common way to invoke the tool, because Puppet will often manage OS-level facilities. Apply your new manifest with root access, either through sudo or from a root shell, as shown in the following transcript:
root@puppetmaster:~# puppet apply puppet_service.pp
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.61 seconds
Notice: /Stage[main]/Main/Service[puppet]/ensure: ensure changed 'running' to 'stopped'
Notice: Applied catalog in 0.15 seconds
Now, Puppet has disabled the automatic startup of its background service for you. Applying the same manifest again has no effect, because the necessary steps are already complete:
root@puppetmaster:~# puppet apply puppet_service.pp
Notice: Compiled catalog for puppetmaster.example.net in environment
production in 0.62 seconds
Notice: Applied catalog in 0.07 seconds
This reflects a standard behavior in Puppet: Puppet resources are idempotent, which means that every resource first compares the actual (system) with the desired (Puppet) state and only initiates actions in case there is a difference (configuration drift).
You will often get this output from Puppet. It tells you that everything is as it should be. As such, this is a desirable outcome, like the all clean output from git status.
Each of the manifests you wrote in the previous section declared one respective resource. Resources are the elementary building blocks of manifests. Each has a type (in this case, notify and service, respectively) and a name or title (Hello, world! and puppet). Each resource is unique to a manifest, and can be referenced by the combination of its type and name, such as Service["puppet"]. Finally, a resource also comprises a list of zero or more attributes. An attribute is a key-value pair, such as "enable => false".
Attribute names cannot be chosen arbitrarily. They are part of the Puppet resource type. Puppet differentiates between two different attributes: parameters and properties. Each resource type supports a specific set of attributes. Parameters describe the way that Puppet should deal with a resource type. Properties describe a specific setting of a resource. Certain parameters are available for all resource types (metaparameters), and some names are just very common, such as ensure. The service type supports the ensure property, which represents the status of the managed process. Its enabled property, on the other hand, relates to the system boot configuration (with respect to the service in question).
You have already seen two properties in action. Let's look at a parameter:
service { 'puppet': ensure => 'stopped', enable => false, provider => 'upstart',}
The provider parameter tells Puppet that it needs to interact with the upstart subsystem to control its background service, as opposed to systemd or init. If you don't specify this parameter, Puppet makes an educated guess. There is quite a multitude of supported facilities to manage services on a system. You will learn more about providers and their automatic choosing later on.
The difference between parameters and properties is that the parameter merely indicates how Puppet should manage the resource, not what a desired state is. Puppet will only take action on property values. In this example, these are ensure => 'stopped' and enable => false. For each such property, Puppet will perform the following tasks:
Test whether the resource is already in sync with the target state
If the resource is not in sync, it will trigger a sync action
A property is considered to be in sync when the system entity that is managed by the given resource (in this case, the upstart service configuration for Puppet) is in the state that is described by the property value in the manifest. In this example, the ensure property will be in sync only if the puppet service is not running. The enable property is in sync if upstart is not configured to launch Puppet at system start.
As a mnemonic concerning parameters versus properties, just remember that properties can be out of sync, whereas parameters cannot.
Puppet also allows you to read your existing system state by using the puppet resource command:
root@puppetmaster:~# puppet resource user root
user { 'root':
ensure => 'present',
comment => 'root',
gid => '0',
home => '/root',
password => '$6$17/7FtU/$TvYEDtFgGr0SaS7xOVloWXVTqQxxDUgH.
eBKJ7bgHJ.hdoc03Xrvm2ru0HFKpu1QSpVW/7o.rLdk/9MZANEGt/',
password_max_age => '99999',
password_min_age => '0',
shell => '/bin/bash',
uid => '0',
}
Please note that some resource types will return read-only attributes (for example, the file resource type will return mtime and ctime). Refer to the appropriate type's documentation.
As you have already witnessed, the output presented by Puppet is rather verbose. As you get more experienced with the tool, you will quickly learn to spot the crucial pieces of information. Let's first take a look at the informational messages, though. Apply the service.pp manifest once more:
root@puppetmaster:~# puppet apply puppet_service.pp
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.48 seconds
Notice: Applied catalog in 0.05 seconds
Puppet took no particular action. You only get two timings: one from the compiling phase of the manifest, and the other from the catalog application phase. The catalog is a comprehensive representation of a compiled manifest. Puppet bases all its efforts concerning the evaluation and syncing of resources on the content of its current catalog.
Now, to quickly force Puppet to show you some more interesting output, pass it a one-line manifest directly from the shell. Regular users of Ruby or Perl will recognize the call syntax:
# puppet apply -e'service { "puppet": enable => true, }'
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.62 seconds
Notice: /Stage[main]/Main/Service[puppet]/enable: enable changed 'false' to 'true'
Notice: Applied catalog in 0.12 seconds.
You instructed Puppet to perform yet another change on the Puppet service. The output reflects the exact change that was performed. Let's analyze this log message:
The
Notice:
keyword at the beginning of the line represents the log level. Other levels include
Warning
,
Error
, and
Debug
The property that changed is referenced with a whole path, starting with
Stage[main]
. Stages are beyond the scope of this book, so you will always just see the default of
main
here
The next path element is
Main
, which is another default. It denotes the class in which the resource was declared. You will learn about classes in
Chapter 4
,
Combining Resources in Classes and Defined Types
Next, is the resource. You already learned that
Service[puppet]
is its unique reference
Finally,
enable
is the name of the property in question. When several properties are out of sync, there will usually be one line of output for each property that gets synchronized
The rest of the log line indicates the type of change that Puppet saw fit to apply. The wording depends on the nature of the property. It can be as simple as
created
, for a resource that is newly added to the managed system, or a short phrase, such as
changed false to true
Another useful command-line switch for puppet apply is the --noop option. It instructs Puppet to refrain from taking any action on unsynced resources. Instead, you only get a log output that indicates what will change without the switch. This is useful in determining whether a manifest would possibly break anything on your system:
root@puppetmaster:~# puppet apply puppet_service.pp --noop
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.63 seconds
Notice: /Stage[main]/Main/Service[puppet]/enable: current_value true, should be false (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.06 seconds
The additional notices about triggered refreshes will be described later, and can be ignored for the moment. You will have a better understanding of their significance after finishing this chapter and Chapter 4, Combining Resources in Classes and Defined Types.
The data type system in Puppet 4 allows you to check and verify whether a variable is of a specific data type. This prevents code from behaving incorrectly when (for example) it expects an array but receives a Boolean value.
The full power of data types will be explained in Chapter 7, New Features from Puppet 4 and 5. Within Puppet manifests, it is possible to check for data types using the regexp control structure.
Puppet has core data types and abstract data types. The core data types are the most commonly used types of data, such as string or integer, whereas abstract data types allow for more sophisticated type validation, such as optional or variant.
Prior to dealing with data types, we must understand the concept of control structures within Puppet manifests.
So far, you have written three simple manifests while following the instructions in this chapter. Each comprised only one resource, and one of them was given on the command line using the -e option. Of course, you would not want to write distinct manifests for each possible circumstance. Instead, just as how Ruby or Perl scripts branch out into different code paths, there are structures that make your Puppet code flexible and reusable for different circumstances.
The most common control element is the if/else block. It is quite similar to its equivalents in many programming languages:
if 'mail_lda' in $needed_services { service { 'dovecot': enable => true }} else { service { 'dovecot': enable => false }}
The Puppet DSL also has a case statement, which is reminiscent of its counterparts in other languages as well:
case $role { ‘imap_server’: { package { ‘dovecot’: ensure => installed, } service { ‘dovecot’: ensure => running, } } /_webservers$/: { service { [‘apache’, ‘ssh’]: ensure => running, } } default: { service { ‘ssh’: ensure => running, } }}
At the second matcher, you can see how it is possible to use regular expressions.
The case statement can also be used to switch to specific code based on variable data types:
case $role { Array: { include $role[0] } String: { include $role } default: { notify { 'This nodes $role variable is neither an Array nor a String':} }}
A variation of the case statement is the selector. It's an expression, not a statement, and can be used in a fashion similar to the ternary if/else operator found in C-like languages:
package { 'dovecot': ensure => $role ? { 'imap_server' => 'installed', /desktop$/ => 'purged', default => 'removed', },}
Similar to the case statement, the selector can also be used to return results, depending on the data types:
package { 'dovecot': ensure => $role ? { Boolean => 'installed', String => 'purged', default => 'removed', },}
The selector should be used with caution, because in more complex manifests, this syntax will impede readability.
With what you've seen this far, you might have got the impression that Puppet's DSL is a specialized scripting language. That is actually quite far from the truth. A manifest is not a script or program. The language is a tool to model a system state through a set of resources, including files, packages, and cron jobs, among others.
The whole paradigm is different from that of scripting languages. Ruby or Perl are imperative languages that are based around statements that will be evaluated in a strict order. The Puppet DSL is declarative, which means that the manifest declares a set of resources that are expected to have certain properties. These resources are put into a catalog, and Puppet then tries to build a path through all declared resources. The compiler parses the manifests in order, but the configurer applies resources in a very different way.
In other words, the manifests should always describe what you expect to be the end result. The specifics of what actions need to be taken to get there are decided by Puppet.
To make this distinction more clear, let's look at an example:
package { 'haproxy': ensure => 'installed',}file {'/etc/haproxy/haproxy.cfg': ensure => file, owner => 'root', group => 'root', mode => '0644', source => 'puppet:///modules/haproxy/etc/haproxy/haproxy.cfg',}service { 'haproxy': ensure => 'running',}
With this manifest, Puppet will make sure that the following state is reached:
The
HAproxy
package is installed.
The
haproxy.cfg
file has specific content, which has been prepared in a file in
/etc/puppet/modules/
.
HAproxy
is started.
To make this work, it is important that the necessary steps are performed in order:
A configuration file cannot usually be installed before the package because there is not yet a directory to contain it
The service cannot start before installation either. If it becomes active before the configuration is in place, it will use the default settings from the package instead
This point is being stressed because the preceding manifest does not, in fact, contain cues for Puppet to indicate such a strict ordering. Without explicit dependencies, Puppet is free to put the resources in any order it sees fit.
