Puppet Installation + Core Concept

I would say this is one the most simple and easy to follow instruction regarding Puppet installation, configuration and concepts. I will install a Puppet Server and Puppet agent (Centos 7.3) for testing completely seperarely, simulating the real scenario.

**************************************************************************************

Introduction

Puppet is a configuration management tool which is producing a repeatable and consistent configuration.

Before I start with the setup, lets understand the concept of how Puppet works. In puppet we don’t have any Push capability from Master server to slave node (agent). So puppet run always start from agent toward Master which contain following steps (as can be seen in Figure A):

  • Node (agent): running an external tool called Facter which gathers all required info (like system name, OS type, memory…) about the node that agent is running and will send it to the Master.
  • Master node will decide based on info that received from Agent, what configuration/files/.. should be chosen.
  • Master node then will create a set of instruction/dependency files (jason format) which is called Catalog and will send it to the Agent node.                            Description: A catalog is a document that describes the desired system state for one specific computer. It lists all of the resources that need to be managed, as well as any dependencies between those resources.
  • Then node will start to apply the catalog which is running set of instruction. It still relies on Repositories like Yum/apt/.. for resolving the dependencies.
  • Then node will create a full report for actions that succeeded or failed and will send it back to the Master node. Or we can configure another tool like PuppetDB to gather all reports for future use.

All communication between puppet master and agents is made in a secure encrypted channel with the help of SSL.

snapshot1

Figure A: Puppet communication

Installation

Puppet Server

As always we have some preparation steps such as changing the Hostname and installing some packages (yum install epel-release), do update and turn of firewald service. If you have problem in this steps, please have a look at xCAT page in my website.

systemctl stop firewalld
systemctl disable firewalld

I install the puppet server from puppetlabs (https://yum.puppetlabs.com/) and not from centos or epel repositories. So first I download the correct repository file from puppetlabs which is Puppet Collection (pc1) and then will install the related tools.

This will create a repo file in /etc/yum.repos.d which is called puppetlabs-pc1.repo.

  • [root@puppetserver ~]# yum install puppetserver

to check the basic default configuration, we can check following location:

  • [root@puppetServer ~]# cat /etc/sysconfig/puppetserver
    # Location of your Java binary (version 7 or higher)
    JAVA_BIN=”/usr/bin/java”
    # Modify this if you’d like to change the memory allocation, enable JMX, etc
    JAVA_ARGS=”-Xms1g -Xmx1g -XX:MaxPermSize=256m”
    # These normally shouldn’t need to be edited if using OS packages
    USER=”puppet”
    GROUP=”puppet”
    INSTALL_DIR=”/opt/puppetlabs/server/apps/puppetserver”
    CONFIG=”/etc/puppetlabs/puppetserver/conf.d”
    # Bootstrap path
    BOOTSTRAP_CONFIG=”/etc/puppetlabs/puppetserver/services.d/,/opt/puppetlabs/server/apps/puppetserver/config/services.d/”
    # SERVICE_STOP_RETRIES can be set here to alter the default stop timeout in
    # seconds. For systemd, the shorter of this setting or ‘TimeoutStopSec’ in
    # the systemd.service definition will effectively be the timeout which is used.
    SERVICE_STOP_RETRIES=60
    # START_TIMEOUT can be set here to alter the default startup timeout in
    # seconds. For systemd, the shorter of this setting or ‘TimeoutStartSec’
    # in the service’s systemd.service configuration file will effectively be the
    # timeout which is used.
    START_TIMEOUT=300
    # Maximum number of seconds that can expire for a service reload attempt before
    # the result of the attempt is interpreted as a failure.
    RELOAD_TIMEOUT=120

We can change the two xms & xmx values:

Xmx: the JVM’s “max heap size” controls the maximum amount of (heap*[1] memory that the JVM process is allowed to request from the operating system).

Xms: (Note that there is another setting, “min heap size”, that is controlled via the -Xms setting; Oracle recommends setting this value to the same value that you use for -Xmx

Due to unsufficinet memory in my system I changed both Xms and Xmx into 1G that be able to start the puppetserver. But you can put a appropriate value based on amount of memory your Puppet Server has and the number of agent nodes you are going to mange.

So now we can start the service: (it might take some time)

  • [root@puppetserver ~]# systemctl status puppetserver

 

Puppet agent (client side)

Here also we need to do some prepataion similar to Master node. Make sure the firewald is stoped or disbaled. The name I chose is puppetagent. And very important, we need to tell the agent where he can find the puppet master which I did from /etc/hosts:

  • [root@puppetAgent ~]# cat /etc/hosts
    127.0.0.1 localhost
    10.10.11.100 puppetAgent
    10.10.11.114 puppet

In the above puppet is refering to the puppert server. However we can do this also in another way by adding following line: (after installing the agent)

cat /etc/puppetlabs/puppet/puppet.conf

[agent]
server = Puppet Server Name/IP add

And for installation, again download the repository file from puppetlabs and install the agent:

And then again download the latest puppet rpm from puppet lab:

rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm

and then install the puppet agent here:

  • [root@puppetAgent ~]# yum install puppet or (yum install puppet-agent)
  • [root@puppetAgent ~]# systemctl start puppet

If the puppet agent start properly, it should send the certificate for signing to the puppet master. The first time you run the Puppet agent, it generates an SSL certificate and sends a signing request to the Puppet master. After the Puppet master signs the agent’s certificate, it will be able to communicate with and control the agent node.

we can check that by running following command on puppet master:

  • [root@puppetserver ~]# puppet cert list
    “puppetagent.xxxx.de” (SHA256) 21:B4:…

 

and now we can sign it by:

  • [root@puppetserver ~]# puppet cert sign puppetagent.xxxx.de
    Notice: Signed certificate request for puppetagent.xxxx.de
    Notice: Removing file Puppet::SSL::CertificateRequest puppetagent.xxxx.de at ‘/var/lib/puppet/ssl/ca/requests/puppetagent.xxxx.de.pem’

and then we can check if it has been signed by:

[we will see + in the front of certificate]

  • [root@puppetserver ~]# puppet cert list –all

We need to source the puppet binaries in our environment by following command:

  • [root@puppetagent ~]# cat /etc/profile.d/puppet-agent.sh
    # Add /opt/puppetlabs/bin to the path for sh compatible users
    if ! echo $PATH | grep -q /opt/puppetlabs/bin ; then
    export PATH=$PATH:/opt/puppetlabs/bin
    fi
  • [root@puppetagent ~]# source /etc/profile.d/puppet-agent.sh

we can do a quick test with following command on our agent:

  • [root@puppetagent ~]# puppet agent –test
    Info: Retrieving pluginfacts
    Info: Retrieving plugin
    Info: Caching catalog for puppetagent.xxxx.de
    Info: Applying configuration version ‘1496836234’
    Notice: Finished catalog run in 0.01 seconds

There are several ways of configuring the puppet agent:

  • can be configured to run regularly which by default is every 30 min. So it mean every 30min it wakes up and check with the puppet master (retrieve catalog) about how to configure the system (how should be the latest configuration status of the system).
  • On demand Manually: like using a command such as “puppet agent -t” which triger the agent to contact the Master node (retrieve the catalog) and do all the needed operation.
  • On demand automatic: with a tools like Mcollective
  • noop: there is a feature called “noop” that we can use for examining the changes that may happen without really doing anything.
  • Masterless puppet: here we use a command “puppet apply xx.pp” which enable agent to read the configuration file locally, compile a catalog and apply changes to a local system without contacting the puppet master.

It is important to note that Puppet master also can have agent service in case we want to test some stuff directly on the puppet master. In this case following 2 commands do the same job which I explain later in deep:

puppet apply name.pp
puppet agent -t

 

Basic Concepts

Here I go through some basic and important concepts of puppert with some examples:

a. facter

Facter is Puppet’s cross-platform system profiling library. It discovers and reports per-node facts, which are available in your Puppet manifests as variables. Facter gathers basic facts about nodes (systems) such as hardware details, network settings, OS type and version, and more.

The facts that can be gathered is useful in many situation. As an example, we created a web server configuration template and want to deploy it on different systems. Based on systems types we want to run ”apache2” for Centos or ”httpd” for Ubuntu.

We can run the command easily to see the list of facts that the tool gathered by:

  • [root@puppetagent ~]# facter

we can also see the content with json format like: facter –json or with yarl format facter –yaml

b. manifests

puppet use a specific language to describe intended configuration. These configuration should be written to a file which has *.pp format and is called manifest file. We need to keep in mind that manifests are not running from top to down, but when puppet create a catalog from them, it will create base on dependencies. In my case, the default manifest directory is located in /etc/puppetlabs/code/environments/production/manifests/ which by default is empty (you can find yours by [find / -type d -name ‘manifests’]. Keep it in mind that puppet will automatically create a catalog from the manifest files that we are writing and that is the real code which will be sent to the Target system which is basically a jason format.

Puppet always begins compiling with the main manifest, which can be either a single file or a directory containing several files. (Some documents also call this the “site manifest.”) Here I create a simple site.pp file as an example:

  • [root@puppetserver manifests]# cat site.pp
    node puppetagent {
    notify{“Good Morning Hossein”: }
    }

and when we run “puppet agent -t” from puppet agent we see the above message.

Description: The Puppet site manifest (site.pp) is the main file that Puppet uses to define global system configuration. A site manifest defines configuration that you want applied to every node, which is ideal for managing system-wide configurations, such as DNS servers, LDAP configuration, and other site-wide settings that are common to all of the nodes. A site manifest can also include node-specific blocks of code that apply to certain nodes. This capability enables you to assign specific configurations to specific nodes within a site manifest.

In the following example, we can see that that site.pp has two parts. The first part is global configuration and it will create a /tmp/test file in every agent in production environment (I explain later) and second part only apply on “puppetagent” node.

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    file {‘/tmp/test’:
    ensure => present,
    mode => ‘0644’,
    content => “Hossein Testing the site manifest\n”
    }
    node puppetagent {
    file{“/etc/motd”:
    ensure => present,
    content => “Hi Hossein and wellcome\n”,
    owner => ‘root’,
    mode => ‘0755’,
    }
    package{“htop”:
    ensure => present,
    }
    package{“httpd”:
    ensure => installed,
    }
    service{“httpd”:
    ensure => running,
    }
    class {‘conditionFacts’:}
    }

c. Puppet Resources

It is important to know that puppet defines everything as a resource. Resource is a building block that determine how we configure/define a system. It defines exact End State of a specific component of the system by specifying a type, a title and a list of attributes as can be seen here:

<type> { <title> :
attribute1 => value1,
attribute2 => value2,
}

Type
The type of a resource determines the system component Puppet manages. Some common types are: user, group, file, service and package. A resource declaration always contains the type of resource being managed. It is obvious that we need to have different resource types based on configuring different part of the system. The list of all resource types can be seen with following command:

  • [root@puppetserver ~]# puppet resource –types
    ….
    user
    host
    group
    computer
    file
    notify
    package
    service
    cron
    mount

Title
The title of a resource identifies an instance of that resource type. The combination of type and title refers to a single unique element managed by puppet, such as a user name joe or a file with path /root/.bashrc.

Attributes
Each resource supports a list of key value pairs called attributes. These attributes provide a detailed description that Puppet uses to manage the resource. For example, the file /root/.bashrc should be present. The user dan should be present and have its login shell set to /bin/bash.

A good example would be following which ensure that a package named apache2 is installed:

package { ‘apache2’:
ensure => present,
}

Now that we know the concept of resources we can define manifest in a better way as a source file (*.pp) that contains one or several resources that is focused on a common application/service. Following is a manifest (webserver.pp) which ensures that a package apache2 is installed and is running on the webserver:

class webserver {

package { ‘apache2’:
ensure => latest,
}

service { ‘apache2’:
ensure => running,
subscribe => Package[‘apache2’],
}
}

I will describe class later. For now is enough to know that class is similar to function in programming.

There is a nice feature in puppet that let us to observe the content of available resources. This helps us to easily generate other puppet codes for other purposes. As an example we can list all available sub-resources (different title) in User resource with following command:

  • root@puppetagent ~]# puppet resource user

And if we want to see the content resource of a specific user, we can use the user title in the command. As an example, we can see the user “root” resource content here:

  • [root@puppetagent ~]# puppet resource user root
    user { ‘root’:
    ensure => ‘present’,
    comment => ‘root’,
    gid => ‘0’,
    home => ‘/root’,
    password => ‘$6$c3ElOuZxeF7q34vl$..QykWt7jht3hwtjbc8bn9GI2N/’,
    password_max_age => ‘99999’,
    password_min_age => ‘0’,
    shell => ‘/bin/bash’,
    uid => ‘0’,
    }
    same for packages, we can see all packages here:
  • [root@puppetserver ~]# puppet resource package

and if we want specific packages we can write its name such as:

  • [root@puppetserver ~]# puppet resource package python
    package { ‘python’:
    ensure => ‘2.7.5-48.el7’,
    }

Important examples:

Among all resource type, maybe the file, package and service is quite important and it deserves to have some examples here.

a. file type

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    node puppetagent {
    file{“/etc/motd”:
    ensure => present,
    content => “Hi Hossein and wellcome\n”,
    owner => ‘root’,
    mode => ‘0755’,
    }
    }

and then easily from agent node:

  • [root@puppetagent ~]# puppet agent -t
  • [root@puppetagent ~]# cat /etc/motd
    Hi Hossein and wellcome

b. package type

here we can install any package we need, based on the package name for our repositoy. Here I have Centos, so I need to make sure the package I want to install exist in the repository. (yum search htop)

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    node puppetagent {
    file{“/etc/motd”:
    ensure => present,
    content => “Hi Hossein and wellcome\n”,
    owner => ‘root’,
    mode => ‘0755’,
    }
    package{“htop”:
    ensure => present,
    }
    }

c. service type

here we want to make sure that apache service is running on the agent. In centos the apache service/package is called httpd. And beside make sure httpd has been installed.

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    node puppetagent {
    file{“/etc/motd”:
    ensure => present,
    content => “Hi Hossein and wellcome\n”,
    owner => ‘root’,
    mode => ‘0755’,
    }
    package{“htop”:
    ensure => present,
    }
    package{“httpd”:
    ensure => installed,
    }
    service{“httpd”:
    ensure => running,
    }
    }

after running “puppet agent -t” on the agent, we can see that service httpd is running (systemctl status httpd).

There is a probability that our manifest does not run in the order we want. In this case we need to explicitly define that we need the package being installed before service get run.

package{“httpd”:
ensure => installed,
}
service{“httpd”:
ensure => running,
require => Package[“httpd”],
}
}

We can refer to a resource by its resource type name (first letter is Capital) and enclose its title in bracket.

Package { ‘puppet’:
ensure => present,
before => service[‘puppet’], # notify => service[‘puppet’],
}

service { ‘puppet’:
ensure => running,
enabled => true,
require => Package[‘puppet’], # subscribe => Package[‘puppet’],
}

so basically here we create a service which run the puppet agent which we have installed in the first manifest. I used both Before and Require in above example, which one of them is enough but better to use both at the same time. There is another 2 metaparameters that functioning quite in a similar way which are Notify & Subscribe. The difference is that it will send (notify) an event to the dependent resource if the dependency changed. So in our case if the puppet agent package being updated, it will send a notify to the service in order to restart the service, since the config files might be changed due to new update/upgrade.

There is another interesting metaparameter which is combination of Notify & Refreshonly parameter that can be used with exec resources. In this case, exec resource will be executed Only if there is a notify (refresh event). In the following example, the exec will be executed when there is a new Puppet agent package.

Package { ‘puppet’:
ensure => latest,
notify => Exec[‘update-facts’],
}

exec { ‘update-facts’:
path => [‘/bin’ ,’/usr/bin’],
command => ‘facter –-yaml > /etc/mcollective/facts.yaml’,
refreshonly => true,usually
}

d. Using facts capability

Here I write a simple class which use facts and then call it from our main site.pp manifest.

  • [root@puppetserver manifests]# cat /etc/puppetlabs/code/environments/production/manifests/conditionFacts.pp
    class conditionFacts {
    if $facts[‘os’][‘name’] == ‘CentOS’ {
    notify{“HostName is ${facts[‘hostname’]}, which is running ${facts[‘os’][‘name’]},  ${facts[‘os’][‘release’][‘full’]} \n”:}
    }
    }
  • [root@puppetserver manifests]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    node puppetagent {


    class {‘conditionFacts’:}
    }

and same as before we can from agent node run the “puppet agent -t” command.

  • [root@puppetagent ~]# puppet agent -t

    Notice: HostName is puppetagent, which is running CentOS, 7.3.1611

    Notice: Applied catalog in 0.42 seconds

Always we need to check facter variable before writing the manifest, since different version of facter tool might show different info:

  • [root@puppetAgent]# facter
    ..
    os => {
    architecture => “x86_64”,
    family => “RedHat”,
    hardware => “x86_64”,
    name => “CentOS”,
    release => {
    full => “7.3.1611”,
    major => “7”,
    minor => “3”
    },

 

d. Environment

Environment is a concept that enables us to define different group of agent nodes and serve each group with completely different main manifests and module paths. I would say the primary usage of environment is to have a chance to test our changes (modules, manifests,..) without breaking the real production systems. By default, all nodes are assigned to a default environment named “production” which is created when we install the puppet.

As a result of Default “production” environment, we have several Base path (manifest, module…) which is hardcode and applies with puppet installation in our system.

d.1 default_manifest
As I mentioned earlier the main manifest is the starting point for compiling a catalog. By default the environment will use the puppet’s global “default_manifest” to find its main manifest, unless it has been clearly defined in “environment.conf” to use another main manifest file/directory. But what is “default_manifest” value:

The default value of “default_manifest” is ./manifests which basically means to use the environment’s own manifests directory. Simply in our case that we have following dir:

/etc/puppetlabs/code/environments/production

Our default_manifest will be “/etc/puppetlabs/code/environments/production/manifest” directory. So if we use following command, it shows the proof:

  • [root@puppetserver ~]# puppet config print manifest
    /etc/puppetlabs/code/environments/production/manifests
  • [root@puppetserver ~]# puppet config print | grep mani
    genmanifest = false
    manifest = /etc/puppetlabs/code/environments/production/manifests
    default_manifest = ./manifests
    disable_per_environment_manifest = false
    ordering = manifest

 

d.2 Base Module
The default module path is a directory which allows us to share a module with all environment. So basically it will be used as a fallback location for modules not found in the environment’s modules directory.

  • [root@puppetserver ~]# puppet config print | grep basemodule
    basemodulepath = /etc/puppetlabs/code/modules:/opt/puppetlabs/puppet/modules

Testing environment

Let’s create a testing environment plus modules and manifests directory.

  • [root@puppetserver ~]# ll /etc/puppetlabs/code/environments/testing/
    total 0
    drwxr-xr-x 2 root root 6 Sep 11 15:05 manifests
    drwxr-xr-x 2 root root 6 Sep 11 15:05 module

and we can create a simple site manifest inside this directory:

  • [root@puppetserver ~]# ll /etc/puppetlabs/code/environments/testing/
    total 0
    drwxr-xr-x 2 root root 6 Sep 11 15:05 manifests
    drwxr-xr-x 2 root root 6 Sep 11 15:05 modules

 

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/testing/manifests/site.pp
    file {‘/tmp/testenv’:
    ensure => present,
    mode => ‘0644’,
    content => “Hossein this is testing environment\n”
    }

There are several ways of devoting a puppet agent(s) to different environment. In my case, at the moment I suggest the most easiest and simple solution. I don’t change any configuration file at the moment which means my puppet agent by default still use Production environment. But when I want to use any manifest/module from Testing environment, I do it simply from command line as follow:

  • [root@puppetagent ~]# puppet agent -t –environment testing
    Info: Using configured environment ‘testing’
    Info: Retrieving pluginfacts
    Info: Retrieving plugin
    Info: Caching catalog for puppetagent.science-computing.de
    Info: Applying configuration version ‘1505145298’
    Notice: Applied catalog in 0.02 seconds

 

E. Separating Data from Code

Before I go through the Module concept, it is important to know that the best way of writing code in puppet (manifests or modules) is to separate the code (manifests) from input configuration/data (values) that enables us to re-use the Manifest/Module for other purposes. There are several data types that can be used for this purpose in puppet which Hiera is the most famous one.

D.1 Hiera

Hiera simply is a pluggable Hierachical Database with key/value lookup capability which can lookup data for puppet manifests. It uses by default Yaml or Json file format.

Since Hiera uses customizable hierarchy to lookup data, we can decide how to structure the data within the organization. As an example, we can have following structure within our organization:

  •  Organization-wide defaults
  •  Specific OS defaults
  •  Specific site defaults

Hiera has 2 built-in data file backends which are: Yaml and Json plus the Puppet data provider which each of them supports 4 data types: (with some examples in yaml)

  • strings
    agent: ‘running’
  • Boolean
    agent_boot: true
  • Hash of values (usually can use all types in a single hash block)
    Java:
    ensure: ‘present’
    version: ‘1.8’
  • Arrays
    puppet-components:
    – facter
    – agent

I would say yaml bachend is the most common one which people are using out there. Therefore I also focus on yaml for my puppet master.

Configuring Hiera

By default puppet looks for hiera configuration file at the location which is specified by hiera_config variable which is Hardcoded.

  • [root@puppetserver ~]# puppet config print | grep hiera_config
    hiera_config = /etc/puppetlabs/puppet/hiera.yaml

As can be seen in our case the hiera configuration file is located at /etc/puppetlabs/puppet/hiera.yaml path which also by default has yaml file format. By default, we have following hiera configuration file:

  • [root@puppetserver ~]# cat /etc/puppetlabs/puppet/hiera.yaml

    :backends:
    – yaml
    :hierarchy:
    – “nodes/%{::trusted.certname}”
    – common
    – global
    :yaml:
    :datadir:

Le’s understand this defaults settings of hiera configuration file. Two very important parts are “hierarchy” and “datadir” parts. The “datadir” obviously store all *.yaml configuration file which contains the real data. Even though you see nothing in the front of datadir in above configuration file, you should know that by default it means following directory in our case (Linux):

/etc/puppetlabs/code/environments/%{environment}/hieradata

However you can also specifically write it in the heira.yaml file (maybe nicer to look at):

:yaml:
:datadir: /etc/puppetlabs/code/environments/%{environment}/hieradata

so we need to make sure that both of our environment (production & testing) has hieradata directory.

  • [root@puppetserver ~]# ls /etc/puppetlabs/code/environments/production/
    environment.conf hieradata manifests modules

 

  • [root@puppetserver ~]# ls /etc/puppetlabs/code/environments/testing/
    hieradata manifests modules

Hierarchy:
The next part of heira.yaml configuration file is hierarchy which defines the Order for looking up data (order for reading *.yaml files to search for data). In the default heira.yaml, the hierarchy is based on nodes and common which basically means:

It looks firstr for a yaml file named after the node’s name which is read from $trusted[‘certname’] variable. So we need to have a nodes directory in our environment hieradata as can be seen here:

/etc/puppetlabs/code/environments/production/hieradata/nodes
/etc/puppetlabs/code/environments/testing/hieradata/nodes

If it couldn’t find the configuration data in nodes directory, then it will look for “common.yaml” file which is intended to be used for common values to be used by all agents. The common file need to be in our datadir :

  • /etc/puppetlabs/code/environments/production/hieradata/
  • /etc/puppetlabs/code/environments/testing/hieradata/

Important: Any changes to the hiera.yaml needs the restart of the puppet master service.

Complete example: Let’s have complete example to understand better the concept.

My hiera.yaml configuration is same as I wrote above:

  • [root@puppetserver ~]# cat /etc/puppetlabs/puppet/hiera.yaml

    :backends:
    – yaml
    :hierarchy:
    – “node/%{::fqdn}”
    – common
    – global
    :yaml:
    :datadir: /etc/puppetlabs/code/environments/%{environment}/hieradata/

The target here is to write a simple manifest like site.pp that write a file in /tmp directory of the agent when has been called. The difference is that we want the real data (such as content, permission, dir being stored in hiera and not directly in manifest). So let’s first write the manifest:

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
    file {hiera(‘filedir’):
    ensure => hiera(‘avail’),
    mode => hiera(‘mode’),
    content => hiera(‘content’)
    }

as can be seen all values are called from hiera. But how the hiera look up for data is based on the hiera.yaml configuration. In our case it first look up for nodes name in node directory, then look up for common.yaml file and at the end if couldn’t find the relevant values in the node and common, will look at global.yaml file. In order to understand the example better, I distribute the values of the 4 parameters (filedir, avail, mode and content) in 3 yaml files as written here:

  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/hieradata/node/puppetagent.hrouhani.org.yaml

    filedir: ‘/tmp/hieraHosseinTestNode’
    avail: ‘present’
  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/hieradata/common.yaml

    filedir: ‘/tmp/hieraHosseinCommon’
    avail: ‘present’
    mode: ‘0644’
  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/hieradata/global.yaml

    filedir: ‘/tmp/hieraHosseinTest’
    avail: ‘present’
    mode: ‘0444’
    content: ‘This is to test hiera yaml written by global’
  • [root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/hieradata/global.yaml

    filedir: ‘/tmp/hieraHosseinTest’
    avail: ‘present’
    mode: ‘0444’
    content: ‘This is to test hiera yaml written by global’

Now we want to test. In our puppet agent, we will run the command:

  • [root@puppetagent ~]# puppet agent -t
    Info: Using configured environment ‘production’
    Info: Retrieving pluginfacts
    Info: Retrieving plugin
    Info: Caching catalog for puppetagent.xxx.de
    Info: Applying configuration version ‘1507648390’
    Notice: /Stage[main]/Main/File[/tmp/hieraHosseinTestNode]/ensure: defined content as ‘{md5}50705a97cfef4737b5e871537cc9611b’
    Notice: Applied catalog in 0.03 seconds

The look up method will first look for filedir value (site.pp) and it will find it in node directory. Same for avail value. Then it will look for mode value, and since it does not exist in node directory, it will go to common.yaml file which will find it. And at the end, it will look for content value which only find it in global.yaml. Please pay attention to the hierarchy for finding values.

  • [root@puppetagent ~]# cat /tmp/hieraHosseinTestNode
    This is to test hiera yaml written by global

 

Some useful commands:

a. puppet agent -t –noop

It only shows the changes that will be apply on the target system (agent).

b. variable that has been defined in global level usually in facts by “$::VaribaleName”

example:

  • if $::operatingsystem == ‘Ubuntu’ {
  •     notify{“Installing on Ubuntu”: }
  • }

 

 

 

 

 

 

 

%d bloggers like this: