DevOps Series – Automation with puppet – Part4
Understatanding Puppet Manifests
Puppet instructions or programs are called manifests. Manifests are generally stored in files with the .pp extension. We learned about resources earlier and manifests are actions with resources. Below code shows a manifest that can be used to add a file to a system with Puppet. When a manifest contains a resource, we say the resource is being declared
A Puppet Manifest
#this file is called manifest.pp file { "motd": path => '/etc/motd', ensure => present, mode => 0640, content => 'Authorized users only!', }
Manifests can be applied, as in using the command puppet apply <manifest-name> individually, or they can be part of the Puppet manifest directory. The directory is, by default,/etc/puppet/manifest. Below code shows the application of a Puppet manifest that changes/etc/motd, based on the previous puppet manifest code.
Puppet Manifest Application
## First, check the contents of /etc/motd # cat /etc/motd This is an initial motd ## Create a Puppet manifest that changes /etc/motd # cat /etc/puppet/manifests/motd.pp file { 'motd': path => '/etc/motd', ensure => present, mode => 0640, content => 'Authorized users only!', } ## Run Puppet in local mode, using the 'apply' Puppet command # puppet apply /etc/puppet/manifests/motd.pp notice: /Stage[main]//File[motd]/content: content changed '{md5}dd41045e84f18dea33427f8d1e0d21ec' to '{md5}ab98686fda944143765f6efbcb59c105' notice: Finished catalog run in 0.04 seconds ## New changes are reflected in /etc/motd # cat /etc/motd Authorized users only!
Note |
A Puppet manifest is very particular about colons and commas. If you miss any of them, you get syntax errors similar to Could not parse for environment production:Syntax error at 'ensure'; expected '}' at /etc/puppet/manifests/motd.pp:3 on node web.example.com '. |
The contents of a Puppet manifest can be conditional statements, variables, functions, and other forms of logic as well. A conditional statement that sets /etc/motd based on the OSs is shown in below code
A conditional statement
## Using the 'facter' command view the value of 'osfamily' # facter osfamily RedHat ## Conditional manifest using the facter 'osfamily' to change '/etc/motd' # cat /etc/puppet/manifests/motd.pp if $osfamily == 'RedHat' { file { 'motd': path => '/etc/motd', ensure => present, mode => 0640, content => 'RedHat users only!', } } ## Check the syntax using the 'parser' functionality of Puppet # puppet parser validate /etc/puppet/manifests/motd.pp ## Check the /etc/motd before making a change # cat /etc/motd This is an initial motd ## Apply the manifest using the 'apply' function # cat /etc/motd Authorized users only!# puppet apply /etc/puppet/manifests/motd.pp notice: /Stage[main]//File[motd]/content: content changed '{md5}ab98686fda944143765f6efbcb59c105' to '{md5}5f87968e2b5271c3622cd12b271bb7a3' notice: Finished catalog run in 0.05 seconds ## Check the motd after applying Puppet changes, and it shows 'RedHat' users only # cat /etc/motd RedHat users only!
Relationships in Puppet Manifests
There are four different metaparameters that define the relationship between resources in Puppet:
-
require
-
before
-
subscribe
-
notify
Note |
The order of resources in a manifest does not determine the order of execution. Puppet builds a dependency graph based on the resources, which then determines the order of execution. |
In below listing, each of the metaparameters is explained further. require means the referenced resource must be applied before the resource that requires it. For instance, with SSH, we need the openssh package to be present before the service is started, so we require the package.
Resource Metaparameters
## REQUIRE package { 'openssh': ensure => present, } service { 'sshd': ensure => running, enable => true, require => Package['openssh'], } ## BEFORE package { 'openssh': ensure => present, before => Service['sshd'], } service { 'sshd': ensure => running, enable => true, } ## SUBSCRIBE file { '/etc/sshd/sshd_config': ensure => present, source => 'puppet:///modules/ssh/sshd_config', } service { 'sshd': ensure => running, enable => true, subscribe => File['/etc/ssh/sshd_config'], } ## NOTIFY file { '/etc/sshd/sshd_config': ensure => present, source => 'puppet:///modules/ssh/sshd_config', notify => Service['sshd'], } service { 'sshd': ensure => running, enable => true, }
before ensures the resource is applied before the referenced resourced.
In the sample code snippet, we are saying that before the service sshd is started, we have to install the opensshpackage. In this case, there are two ways of ensuring openssh package is present before attempting to start the service. One way is to use the require metaparameter; the other is to use the before metaparameter. You can use either of these options to get the job done. No method is better than the other; it’s your preference.
subscribe and notify have similar relationships as require and before.
notify sends a notification to the resource requested if a change occurs in the resource. For instance, when the sshd_config file changes, we ask Puppet to notify the sshd service so it can be restarted. Another way of handling this is to tell the sshd service to subscribe to the sshd_config file, so that when we notice any changes to it, we restart the service.
To summarize, if a resource such as sshd is dependent on another resource, such as/etc/sshd/sshd_config file, then in the definition of sshd you can use the metaparametersubscribe so that any time there is a change in the config file, sshd is made aware of the change. Or, in the definition of the sshd_config file, you could use the metaparameter notify, so that each time sshd_config is change, it informs the sshd service.
Similarly, if a service such as sshd requires a package such as OpenSSH, then you can use the metaparameter require in the sshd definition or you can use the metaparameter before in the OpenSSH configuration file definition.