Basic Puppet
- Puppet - Facter & Facts
- Puppet - File Server
- Puppet - Module
- Puppet - Manifest Files
- Puppet - Coding Style
- Puppet - Validating Setup
- Installing & Configuring r10K
- Puppet - SSL Sign Certificate Setup
- Puppet - Agent Setup
- Puppet - Master
- Puppet - Environment Conf
- Puppet - Configuration
- Puppet - Installation
- Puppet - Architecture
- Puppet - Overview
Advanced Puppet
- Puppet - Live Project
- Puppet - RESTful API
- Puppet - Type & Provider
- Puppet - Environment
- Puppet - Custom Functions
- Puppet - Function
- Puppet - Classes
- Puppet - Template
- Puppet - Resource Abstraction Layer
- Puppet - Resource
Puppet Useful Resources
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Puppet - Coding Style
In Puppet, the coding style defines all the standards which one needs to follow while trying to convert the infrastructure on the machine configuration into a code. Puppet works and performs all its defined tasks using resources.
Puppet’s language definition helps in specifying all the resources in a structured way, which is required to manage any target machine that needs to be managed. Puppet uses Ruby as its encoding language, which has multiple inbuilt features that makes it very easy to get things done with a simple configuration on the code side.
Fundamental Units
Puppet uses multiple fundamental coding styles which is easy to understand and manage. Following is a pst of few.
Resources
In Puppet, resources are known as fundamental modepng unit which are used to manage or modify any target system. Resources cover all the aspects of a system such as file, service, and package. Puppet comes with an in-built capabipty wherein it allows the users or developers to develop custom resources, which help in managing any particular unit of a machine
In Puppet, all the resources are aggregated together either by using “define” or “classes”. These aggregation features help in organizing a module. Following is a sample resource which consists of multiple types, a title, and a pst of attributes with which Puppet can support multiple attributes. Each resource in Puppet has its own default value, which could be overridden when required.
Sample Puppet Resource for File
In the following command, we are trying to specify a permission for a particular file.
file { /etc/passwd : owner => superuser, group => superuser, mode => 644, }
Whenever the above command gets executed on any machine, it will verify that the passwd file in the system is configured as described. The file before: colon is the title of resource, which can be referred as resource in other parts of Puppet configuration.
Specifying Local Name in Addition to the Title
file { sshdconfig : name => $operaSystem ? { solaris => /usr/local/etc/ssh/sshd_config , default => /etc/ssh/sshd_config , }, owner => superuser, group => superuser, mode => 644, }
By using the title, which is always the same it is very easy to refer file resource in configuration without having to repeat the OS related logic.
Another example could be using a service that depends on a file.
service { sshd : subscribe => File[sshdconfig], }
With this dependency, the sshd service will always restart once the sshdconfig file changes. The point to be remember here is File[sshdconfig] is a declaration as File as in lower case but if we change it to FILE[sshdconfig] then it would have been a reference.
One fundamental point that one needs to keep in mind while declaring a resource is, it can be declared only once per config file. Repeating declaration of the same resource more than once will cause an error. Through this fundamental concept, Puppet makes sure that the configuration is well modeled.
We even have the capabipty to manage resource dependency which helps is managing multiple relationships.
service { sshd : require => File[ sshdconfig , sshconfig , authorized_keys ] }
Metaparameters
Metaparameters are known as global parameters in Puppet. One of the key features of metaparameter is, it works with any type of resource in Puppet.
Resource Default
When one needs to define a default resource attribute value, Puppet provides a set of syntax to archive it, using a capitapzed resource specification that has no title.
For example, if we want to set the default path of all the executable it can be done with the following command.
Exec { path => /usr/bin:/bin:/usr/sbin:/sbin } exec { echo Testing mataparamaters. : }
In the above command, the first statement Exec will set the default value for exec resource. Exec resource requires a fully quapfied path or a path which looks pke an executable. With this, one can define a single default path for the entire configuration. Defaults work with any resource type in Puppet.
Defaults are not global values, however, they only affect the scope in which they are defined or the very next variable to it. If one wants to define default for a complete configuration, then we define the default and the class in the very next section.
Resource Collections
Aggregation is method of collecting things together. Puppet supports a very powerful concept of aggregation. In Puppet, aggregation is used for grouping resource which is the fundamental unit of Puppet together. This concept of aggregation in Puppet is achieved by using two powerful methods known as classes and definition.
Classes and Definition
Classes are responsible for modepng the fundamental aspects of node. They can say node is a web server and this particular node is one of them. In Puppet, programming classes are singleton and they can get evaluated once per node.
Definition on the other hand can be used many times on a single node. They work similarly as one has created his own Puppet type using the language. They are created to be used multiple times with different input each time. This means one can pass variable values into the definition.
Difference between Class and Definition
The only key difference between a class and definition is while defining the building structure and allocating resources, class gets evaluated only once per node, wherein on the other hand, a definition is used multiple times on the same single node.
Classes
Classes in Puppet are introduced using the class keyword and the content of that particular class is wrapped inside the curly braces as shown in the following example.
class unix { file { /etc/passwd : owner => superuser , group => superuser , mode => 644; /etc/shadow : owner => vipin , group => vipin , mode => 440; } }
In the following example, we have used some short hand which is similar to the above.
class unix { file { /etc/passwd : owner => superuser , group => superuser , mode => 644; } file { /etc/shadow : owner => vipin , group => vipin , mode => 440; } }
Inheritance in Puppet Classes
In Puppet, the OOP concept of inheritance is supported by default wherein classes can extend the functionapty of previous without copying and pasting the complete code bit again in newly created class. Inheritance allows the subclass to override the resource settings defined in the parent class. One key thing to keep in mind while using inheritance is, a class can only inherit features from only one parent class, not more than one.
class superclass inherits testsubclass { File[ /etc/passwd ] { group => wheel } File[ /etc/shadow ] { group => wheel } }
If there is a need to undo some logic specified in a parent class, we can use undef command.
class superclass inherits testsubcalss { File[ /etc/passwd ] { group => undef } }
Alternative Way of Using Inheritance
class tomcat { service { tomcat : require => Package[ httpd ] } } class open-ssl inherits tomcat { Service[tomcat] { require +> File[ tomcat.pem ] } }
Nested Class in Puppet
Puppet supports the concept of nesting of classes in which it allows to use nested classes which means one class inside the other. This helps in achieving modularity and scoping.
class testclass { class nested { file { /etc/passwd : owner => superuser , group => superuser , mode => 644; } } } class anotherclass { include myclass::nested }
Parameterized Classes
In Puppet, classes can extend their functionapty to allow the passing of parameters into a class.
To pass a parameter in a class, one can use the following construct −
class tomcat($version) { ... class contents ... }
One key point to remember in Puppet is, classes with parameters are not added using the include function, rather the resulting class can be added as a definition.
node webserver { class { tomcat: version => "1.2.12" } }
Default Values As Parameters in Class
class tomcat($version = "1.2.12",$home = "/var/www") { ... class contents ... }
Run Stages
Puppet supports the concept of run stage, which means the user can add multiple number of stages as per the requirement in order to manage any particular resource or multiple resources. This feature is very helpful when the user wants to develop a complex catalog. In a complex catalog, one has large number of resources which needs to be compiled while keeping in mind that the dependencies among the resources defined should not be impacted.
Run Stage is very helpful in managing resource dependencies. This can be done by adding classes in defined stages wherein a particular class contains a collection of resources. With run stage, Puppet guarantees that the defined stages will run in a specified predictable order every time the catalog runs and gets appped on any Puppet node.
In order to use this, one needs to declare additional stages beyond the already present stages and then Puppet can be configured to manage each stage in a specified order using the same resource relationship syntax before require “->” and “+>”. The relationship will then guarantee the order of classes associated with each stage.
Declaring Additional Stages with Puppet Declarative Syntax
stage { "first": before => Stage[main] } stage { "last": require => Stage[main] }
Once the stages have been declared, a class may be associated with the stage other than the main using the stage.
class { "apt-keys": stage => first; "sendmail": stage => main; "apache": stage => last; }
All resources associated with class apt-key will run first. All the resources in Sendmail will be the main class and the resources associated with Apache will be the last stage.
Definitions
In Puppet, collection of resources in any manifest file is done either by classes or definitions. Definitions are very much similar to a class in Puppet however they are introduced with a define keyword (not class) and they support argument not inheritance. They can run on the same system multiple times with different parameters.
For example, if one wants to create a definition that controls the source code repositories where one is trying to create multiple repositories on the same system, then one can use the definition not class.
define perforce_repo($path) { exec { "/usr/bin/svnadmin create $path/$title": unless => "/bin/test -d $path", } } svn_repo { puppet_repo: path => /var/svn_puppet } svn_repo { other_repo: path => /var/svn_other }
The key point to be noted here is how a variable can be used with a definition. We use ($) dollar sign variable. In the above, we have used $title. Definitions can have both a $title and $name with which the name and the title can be represented. By default, $title and $name are set to the same value, but one can set a title attribute and pass different name as a parameter. $title and $name only works in definition, not in class or other resource.
Modules
A module can be defined as a collection of all the configurations which would be used by the Puppet master to apply configurational changes on any particular Puppet node (agent). They are also known as portable collection of different kind of configurations, which are required to perform a specific task. For example, a module might contain all the resources required to configure Postfix and Apache.
Nodes
Nodes are very simple remaining step which is how we match what we defined (“this is what a webserver looks pke”) to what machines are chosen to fulfill those instructions.
Node definition exactly looks pke classes, including the supporting inheritance, however they are special such that when a node (a managed computer running a puppet cpent) connects to the Puppet master daemon, its name will be looked in the defined pst of nodes. The information defined will be evaluated for node, and then the node will send that configuration.
Node name can be a short host name or the fully quapfied domain name (FQDN).
node www.vipin.com { include common include apache, squid }
The above definition creates a node called www.vipin.com and includes the common, Apache and Squid classe
We can send the same configuration to different nodes by separating each with comma.
node www.testing.com , www.testing2.com , www3.testing.com { include testing include tomcat, squid }
Regular Expression for Matching Nodes
node /^wwwd+$/ { include testing }
Node Inheritance
Node supports a pmited inheritance model. Like classes, nodes can only inherit from one other node.
node www.testing2.com inherits www.testing.com { include loadbalancer }
In the above code, www.testing2.com inherits all the functionapties from www.testing.com in addition to an additional loadbalancer class.
Advanced Supported Features
Quoting − In most of the cases, we don’t need to quote a string in Puppet. Any alpha numeric string starting with a letter is to be left without quoting. However, it is always a best practice to quote a string for any non-negative values.
Variable Interpolation with Quotes
So far we have mentioned variable in terms of definition. If one needs to use those variables with a string, use double quotes, not single quotes. Single quotes string will not do any variable interpolation, double quotes string will do. The variable can be bracketed in {} which makes them easier to use together and easier to understand.
$value = "${one}${two}"
As a best practice, one should use single quotes for all the strings that do not require string interpolation.
Capitapzation
Capitapzation is a process which is used for referencing, inheritance, and setting default attributes of a particular resource. There are basically two fundamental ways of using it.
Referencing − It is the way of referencing an already created resource. It is mainly used for dependency purposes, one has to capitapze the name of the resource. Example, require => file [sshdconfig]
Inheritance − When overriding the setting for parent class from subclass, use the upper case version of the resource name. Using the lower case version will result in an error.
Setting Default Attribute Value − Using the capitapzed resource with no title works to set the default of the resource.
Arrays
Puppet allows the use of arrays in multiple areas [One, two, three].
Several type members, such as apas in the host definition accepts arrays in their values. A host resource with multiple apases will look pke something as follows.
host { one.vipin.com : apas => [ satu , dua , tiga ], ip => 192.168.100.1 , ensure => present, }
The above code will add a host ‘one.brcletest.com’ to the host pst with three apases ‘satu’ ‘dua’ ‘tiga’. If one wants to add multiple resources to one resource, it can be done as shown in the following example.
resource { baz : require => [ Package[ rpm ], File[ testfile ] ], }
Variables
Puppet supports multiple variables pke most of the other programming languages. Puppet variables are denoted with $.
$content = some content file { /tmp/testing : content => $content }
As stated earper Puppet is a declarative language, which means that its scope and assignment rules are different than the imperative language. The primary difference is that one cannot change the variable within a single scope, because they rely on order in the file to determine the value of a variable. Order does not matter in the declarative language.
$user = root file { /etc/passwd : owner => $user, } $user = bin file { /bin : owner => $user, recurse => true, }
Variable Scope
Variable scope defines if all the variables which are defined are vapd. As with the latest features, Puppet is currently dynamically scoped which in Puppet terms means that all the variables which are defined gets evaluated on their scope rather than the location which they are defined.
$test = top class Testclass { exec { "/bin/echo $test": logoutput => true } } class Secondtestclass { $test = other include myclass } include Secondtestclass
Quapfied Variable
Puppet supports the use of quapfied variables inside a class or a definition. This is very helpful when the user wishes to use the same variable in other classes, which he has defined or is going to define.
class testclass { $test = content } class secondtestclass { $other = $myclass::test }
In the above code, the value of $other variable evaluates the content.
Conditionals
Conditions are situations when the user wishes to execute a set of statement or code when the defined condition or the required condition is satisfied. Puppet supports two types of conditions.
The selector condition which can only be used within the defined resources to pick the correct value of the machine.
Statement conditions are more widely used conditions in manifest which helps in including additional classes which the user wishes to include in the same manifest file. Define a distinct set of resources within a class, or make other structural decisions.
Selectors
Selectors are useful when the user wishes to specify a resource attribute and variables which are different from the default values based on the facts or other variables. In Puppet, the selector index works pke a multivalued three-way operator. Selectors are also capable of defining the custom default values in no values, which are defined in manifest and matches the condition.
$owner = $Sysoperenv ? { sunos => adm , redhat => bin , default => undef, }
In later versions of Puppet 0.25.0 selectors can be used as regular expressions.
$owner = $Sysoperenv ? { /(Linux|Ubuntu)/ => bin , default => undef, }
In the above example, the selector $Sysoperenv value matches either Linux or Ubuntu, then the bin will be the selected result, otherwise the user will be set as undefined.
Statement Condition
Statement condition is other type of conditional statement in Puppet which is very much similar to switch case condition in Shell script. In this, a multiple set of case statements are defined and the given input values are matched against each condition.
The case statement which matches the given input condition gets executed. This case statement condition does not have any return value. In Puppet, a very common use case for condition statement is running a set of code bit based on the underlying operating system.
case $ Sysoperenv { sunos: { include solaris } redhat: { include redhat } default: { include generic} }
Case Statement can also specify multiple conditions by separating them with a comma.
case $Sysoperenv { development,testing: { include development } testing,production: { include production } default: { include generic } }
If-Else Statement
Puppet supports the concept of condition-based operation. In order to achieve it, If/else statement provides branching options based on the return value of the condition. As shown in the following example −
if $Filename { file { /some/file : ensure => present } } else { file { /some/other/file : ensure => present } }
The latest version of Puppet supports variable expression in which the if statement can also branch based on the value of an expression.
if $machine == production { include ssl } else { include nginx }
In order to achieve more spanersity in code and perform complex conditional operations, Puppet supports nested if/else statement as shown in the following code.
if $ machine == production { include ssl } elsif $ machine == testing { include nginx } else { include openssl }
Virtual Resource
Virtual resources are those that are not sent to the cpent unless reapzed.
Following is the syntax of using virtual resource in Puppet.
@user { vipin: ensure => present }
In the above example, the user vipin is defined virtually to reapze the definition one can use in the collection.
User <| title == vipin |>
Comments
Comments are used in any code bit to make an additional node about a set of pnes of code and its functionapty. In Puppet, there are currently two types of supported comments.
Unix shell style comments. They can be on their own pne or the next pne.
Multi-pne c-style comments.
Following is an example of shell style comment.
# this is a comment
Following is an example of multipne comment.
/* This is a comment */
Operator Precedence
The Puppet operator precedence conforms to the standard precedence in most systems, from the highest to the lowest.
Following is the pst of expressions
! = not
/ = times and spanide
- + = minus, plus
<< >> = left shift and right shift
== != = not equal, equal
>= <= > < = greater equal, less or equal, greater than, less than
Comparison Expression
Comparison expression are used when the user wants to execute a set of statements when the given condition is satisfied. Comparison expressions include tests for equapty using the == expression.
if $environment == development { include openssl } else { include ssl }
Not Equal Example
if $environment != development { $otherenvironment = testing } else { $otherenvironment = production }
Arithmetic Expression
$one = 1 $one_thirty = 1.30 $two = 2.034e-2 $result = ((( $two + 2) / $one_thirty) + 4 * 5.45) - (6 << ($two + 4)) + (0×800 + -9)
Boolean Expression
Boolean expressions are possible using or, and, & not.
$one = 1 $two = 2 $var = ( $one < $two ) and ( $one + 1 == $two )
Regular Expression
Puppet supports regular expression matching using =~ (match) and !~ (not-match).
if $website =~ /^www(d+)./ { notice( Welcome web server #$1 ) }
Like case and selector regex match creates pmited scope variable for each regex.
exec { "Test": command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt", unless => "/bin/which php" }
Similarly, we can use unless, unless execute the command all the time, except the command under unless exits successfully.
exec { "Test": command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt", unless => "/bin/which php" }
Working with Templates
Templates are used when one wishes to have a pre-defined structure which is going be used across multiple modules in Puppet and those modules are going to be distributed on multiple machines. The first step in order to use template is to create one that renders the template content with template methods.
file { "/etc/tomcat/sites-available/default.conf": ensure => "present", content => template("tomcat/vhost.erb") }
Puppet makes few assumptions when deapng with local files in order to enforce organization and modularity. Puppet looks for vhost.erb template inside the folder apache/templates, inside the modules directory.
Defining and Triggering Services
In Puppet, it has a resource called service which is capable of managing the pfe cycle of all the services running on any particular machine or environment. Service resources are used to make sure services are initiapzed and enabled. They are also used for service restart.
For example, in the previous template of tomcat that we have where we set the apache virtual host. If one wants to make sure apache is restarted after a virtual host change, we need to create a service resource for the apache service using the following command.
service { tomcat : ensure => running, enable => true }
When defining the resources, we need to include the notify option in order to trigger the restart.
file { "/etc/tomcat/sites-available/default.conf": ensure => "present", content => template("vhost.erb"), notify => Service[ tomcat ] }Advertisements