Puppet Notes
Puppet focuses on modelling infrastructure than on procedures. A configuration consists of different resources, users, and parameters.
A profile is a set of configurations for one type of service, for example profile for web server or profile for database.
A role is a collection of profiles. Each host is assigned one role set that defines the host’s functions.
Puppet generates reports of the systems it runs on, which can be used to run inventories, etc.
Puppet keeps systems in a desired state, providing a much easier process to make corrections if anything goes wrong.
By default, puppet runs every 30 minutes to compare system state to desired state.
Node – Individual Host managed by Puppet.
Resources – Single units of configuration in Puppet, example, files, system users.
Class – A collection of Puppet code that makes sense as a logical group. Classes group resources under a name that can be used in other code
Manifest – Text file for holding Puppet Code. .pp file type. A manifest should contain a single class or defined resource type.
Profile – A class that defines a specific set of configurations. Generally grouping together other classes with specific parameters. Profile should be limited in the scope it provides.
Role – A class that defines the business role of a node. Built of several profile classes. Each node must have only one role. Identical nodes should also have unique roles assigned to them. Code Duplication is encouraged though.
Vagrant - Open-source software product for building and maintaining portable virtual software development environments.
Install Vagrant and VirtualBox on host.
cd to the directory of vagrant file. “vagrant up” provisions VM by downloading the box and “vagrant ssh” logs into the machine through SSH.
rpm -Uvh https://yum.puppet.com/puppet6-release-el-7.noarch.rpm
yum install -y puppetserver git
vi /etc/config/puppetserver à change JAVA_ARGS to modify the minimum and maximum amount of memory for the process
systemctl start puppetserver
systemctl enable puppetserver
Puppet Master/Agent config file à /etc puppetlabs/puppet/puppet.conf
Configure the puppet agent to point to the master as follows:
[agent]
server = master.puppet.vm
Also, in .bash_profile change $PATH so that puppet commands can be used.
PATH=$PATH:/opt/puppetlabs/puppet/bin
source .bash_profile
gem à tool to install ruby based packages. Package Manager for Ruby.
gem install r10k
r10k helps in managing environment configurations related to different kind of environments that we can configure in Puppet such as development, testing, and production.
puppet agent –test
Version Control allows to track changes in software over a period of time.
git only tracks changes to files. It only stores changes on a commit.
Setup a Control Repository to setup Version Control for Puppet. r10k points to the control repo. On running it the code will be deployed to the puppet master from the control repo. Control Repo is setup in such a way that r10k understands.
Puppet will not work in a git branch called master due to the confusion between the puppet ‘master’ and the ‘master’ branch.
r10k configuration file - /etc/puppetlabs/r10k/r10k.yaml
:cachedir: - directory where r10k will check any modules that we are using form the forge before copying them into place in the repository
:sources:
:my-org:
remote: ‘https://github.com/somegithubrepo/control_repo.git’
basedir: ‘/etc/puppetlabs/code/environments’
remote à address of git repo
basedir à location where r10k will check for modules and configurations. By default these files are stored in the environments directory as mentioned above.
.yaml files are whitespace sensitive. YAML is a human-readable data-serialization language. It is commonly used for configuration files.
Data serialization is the process of converting structured data to a format that allows sharing or storage of the data in a form that allows recovery of its original structure. Serialization (or serialisation) is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).
YAML files start with — on the first line. (three dashes)
r10k deploy environment -p
Resources – A way of defining a specific unit of configuration. For example, file, system user.
Example :
## Name of the resource declaration, for file resources it is the full path for the managed resource. also called namevar line.
file { ‘/root/README’:
##first parameter of the resource telling puppet to ensure that it is a file, other types – directory, link.
using absent deletes file. Hash rocket symbol =>;
ensure =>; file,
##The content of the file. When puppet runs it modifies/creates/does nothing to the file to match the contents of the file to this. Trailing commas must be entered to differentiate parameters. Comma on last line is optional though.
content =>; ‘hello world’,
}
Example:
for a service resource, name of service, its state – running/stopped/absent, enable on boot.
service { ‘crond’:
ensure =>; running,
enable =>; true,
}
site.pp is the first file where the puppet agent looks for system configuration when it is run.
site.pp à
node default {
file { ‘/root/README’:
ensure =>; file,
content =>; ‘This is a readme’,
owner =>; ‘root’,
}
}
Puppet doesn’t allow the same resource to be declared more than once for the same node. Duplicate declarations can lead to an ambiguous state.
https://puppet.com/docs/puppet/6.7/type.html - Built-In resource types.
Classes – Including a set of resources by a name. Wrapper of resource declarations. Declaring a specific class on a node or a set of models is called classification.
Include allows declaring the same class more than once.
Nested classes work within Puppet, as it allow defining logical units of configuration and then compose them as higher levels of abstraction.
Puppet code can be packaged into modules.
https://forge.puppet.com – Available and Downloadable Puppet Modules.
Types of Modules
Installing Module:
Create a new ‘Puppetfile’ in the repo:
mod ‘puppet/nginx’
mod ‘puppetlabs/stdlib’
mod ‘puppetabs/concat’
Version Numbers can be added next to the module name in the Puppetfile, which has both pros and cons. Having no version numbers will always keep the modules updated on the host, while using version numbers rules out chances of an inconsistency and incompatibility on version upgrades.
Profile is a wrapper for a subnet of a configuration and should be limited to single unit of configuration/service, such as a web server, and a different profile for a database. Roles should be made up of only profiles.
Modules are a structured set of directories and files that follow the standards that Puppet expects.
A node will only match one node definition and there is no inheritance. One a node name is matched, the default node will be ignored.
environment.conf à tell puppet the location of roles, profiles, and modules.
modulepath = site:modules:$basemodulepath
site/profile/manifests/app.pp
site/role/manifests/app_server.pp
Node Definition in site.pp
Orchestration describes automated arrangement, coordination, and management of complex computer systems, and services.
Orchestration using Puppet;
- Mcollective
- Puppet Enterprise
- Ansible
MCollective / Marionette Collective – It’s a way of triggering actions on nodes, which could a simple Puppet run or running sophisticated reports on every node in the infrastructure. It operates on a Publish-Subcribe Model, in which a single central server, generally the Puppet master maintains a queue such as ActiveMQ or RabbitMQ and other nodes publish and subscribe data to that queue’s server, hence tolerant of spotty connections. Downside - Impossible to ensure that a machine has actually received the message. Puppet Enterprise introduces a push style communication between server and nodes. App Orchestration involves updating application parameters on nodes.
Puppet Job Tool is used for simple tasks such as doing puppet runs.
Ansible is agentless and uses SSH. Doesn’t manage the desire state as well as Puppet. Ansible for Orchestration and Puppet for Desired State.
Another simple method for orchestration using SSH to trigger puppet runs.
A Puppet Agent Run
- Trigger Facter to collect details about system
- Submit details to the master
- Master looks at the submitted facts and determine relevant code and compile a catalog.
o The catalog is a raw representation of what needs to happen on that node and in what order. It is not human readable.
- Master responds to the agent with the catalog
- Agent takes the catalog and enforces the changes
- Agent generates Reports and send to the master
o Metadata
o Status
o Events
o Logs
o Metrics
Puppet Enterprise has GUI.
Facter is the tool that Puppet uses to gather facts about a node, in order to figure out what needs to done on that node.
facter timezone
facter fqdn
Facter runs in the beginning of a Puppet run.
facter os
facter os.family à generate singular/child information in this manner
Facts are kind of just variables set by Puppet. Use double quotes for strings containing variables to allow those to expand. Add curly braces around the facts name after the dollar sign.
Facts can generate all kind of system information.
Modules
init.pp – contains the same class name as the module name
Class naming conventions for modules – name_of_module::name_of_directory::name_of_file
files directory contains any static files to be used with the module, for example, configuration files.
templates directory contains any dynamics files. Templates allow the creation of configuration files using dynamically attained information.
lib directory contains additional code to extend the functionality of puppet.
root of every module contains a metadata.json file, it is used by the forge to fill in the details for that module.
Puppet development Kit.
Order of code in manifest may not be the order executed by puppet. Meta-parameters can be used to order manifests. Puppet will by default use manifest ordering. before executes the current resource before the referenced. to reference to a resource, the first letter of the resource type is capital followed by the resource name in square brackets.
Arrays can also be used to order resources.
Example:
Both a require and before parameters can be set on the same resource if that is required to happen between two resources.
Other ordering parameters:
- notify
- subscribe
These will trigger a refresh to the subsequent resource.
Parameters can also be used within classes. To do so, in the class definition, define the parameters in circle brackets before the first curly brace. This option allows passing manual arguments or use the defaults as defined. To declare such classes, the same syntax as a resource is used with the resource type being ‘class’.
Templates allow flexibility while generating dynamic text files, with changing outputs.
.erb – Embedded Ruby Template
.epp – Puppet Template
Configuring puppet is about defining the final desired state. Puppet itself will figure out the actual process required to do so.
It’s essentially a modelling language.
Resources are the individual building blocks for Puppet.
Idempotency – Only changing something that is not in the desired state.
Exec – allows to run arbitrary code on a system being managed. From puppet’s perspective exec is just another resource. First see if the desired state already exists.
Defined Resource Types – Made up of other resources.
More advanced method for creating custom resources, which is usually referred to as “type in providers.” This method makes sense for resources that can’t be constructed from other existing resource types.
Class in Puppet is a simple way of organizing code.
Class definition and Class declaration: Class definition means just writing the code in the class, and doesn’t affect anything in the processes. A class needs to be declared. It’s roughly equivalent to copying and pasting a class definition.
Class Declaration: The same way as resource or use include.
Puppet allow enforcing data types for parameters.
Using a params class to check OS facts and match with the appropriate OS. fail() function is also used.
Relationship Metaparameters: These can be applied to any resource to order code and resources. It’s referenced path is looked up in the code and that sets the order for that.
Subscribe: Anytime when one resource changes, then anything subscribed that resource will be trigerred when puppet runs. For eg, a service and a config file.
Notify: Notify the service anytime it changes.
Each resource can only be used once per node.
Classes can be used as defined resources by replacing the word ‘class’ with ‘define’.
Set resource title based on the parameters that the custom type accepts.
In Puppet, variables cannot be resigned, and hence are always the same.
String Interpolation: Using a variable value when defining another variable. Example
$var2 = ‘Bob’
$var1 = “Hello ${var2}”
Use double quotes only when doing string interpolation, for all other things use single quotes.
Arrays can be used in Puppet to define resources.
Any non-empty variable in Puppet will evaluate as true.
‘Unless’ triggers if the condition evaluates to false.
default values can be assigned in case and selectors using ‘default’
Selectors are somewhat same as case , but these are used for matching variables.
The ‘each’ iterator allows to define resources for each item in an array.
Puppet Functions are commands that do something in code as compared to resources which do something on the agent.
Functions are executed when the catalog is compiled. Resources are executed when the catalog is applied.
Templates are loaded via Functions.
Lookup function allows to retrieve data form Hiera.
File sources – puppet:///modules/modulename/directory/motd.txt, an alternate file server can be used by entering the server name after two slashes.
puppet://<SERVER>;/<MOUNT POINT>;/<PATH>;
Resource Defaults can be assigned by defining a resource with that resource type name, the first letter capital.
puppet resource à command shows the Puppet representation of the resource.
Example, puppet resource file /tmp/test
Resource Syntax: :
type { ‘title’: parameter =>; ‘value’,}
Running puppet resource with a parameter=value, modifies the resource to add the value specified.
Example: sudo puppet resource file /tmp/test content=’Hello Puppet!’
This command installs the httpd package:puppet resource package httpd ensure=present
In a default monolithic master installation, the Puppet master server also hosts several supporting services such as the PE console services and PuppetDB. In larger deployments these services may be distributed across other servers to improve performance and provide redundancy.
The Puppet agent begins a Puppet run by sending a catalog request to the Puppet master. This request includes some information about the agent system provided by a tool called Facter. The Puppet master uses this information from Facter along with your Puppet code to compile a catalog that tells the agent exactly how the resources on its system should be configured.
The catalog is the final list of system resources that define the desired state for an agent node. The puppet master sends the catalog back to the agent, and with the help of the providers the agent determines the resource state and performs steps as necessary.
All Puppet agent-master communication happens over SSL, therefore a CSR is submitted by an agent on first connection attempt which needs to be signed by the master.
puppetserver ca listpuppetserver ca sign –certname agent.puppet.vm
On the first successful puppet agent run there is a lot of clutter displayed on the screen, most of what you see is a process called pluginsync. During pluginsync, any extensions installed on the master (such as custom facts, resource types, or providers) are copied to the Puppet agent before the Puppet run continues. This ensures that the agent has all the tools it needs to correctly apply the catalog.
The Puppet agent can be configured to fail over to the cached catalog if it is unable to connect to the master.
When the Puppet Master receives a catalog request, it begins the process of node classification to determine what Puppet code will be applied to generate a catalog for the requesting agent.
3 ways of Handling node classification;
- site.pp – This file contains node definitions, providing the most direct view of how node classification works.
- GUI node classifier on the Puppet Enterprise Console.
- External Node Classifier(ENC) – It can be any executable that takes the name of a node as an argument and returns a YAML file with the puppet code for that node.
site.pp Manifest
When a puppet agent contacts the master, it checks for any node definitions in site.pp matching the agent’s system name.
The parameter that uses the resource title as its default is called a namevar.
Manifest and Classes
Manifest is Puppet code saved to a file with the .pp extension. This code is written in the Puppet domain specific language (DSL).
puppet apply à Apply manifest directly without having to classify the node and triggering a puppet agent run.
A class is named block of Puppet code. Defining a class combines a group of resources into single reusable and configurable unit. Once defined, a class can then be declared to tell Puppet to apply the resources it contains.
A module is a directory structure that lets Puppet keep track of where to find the manifests that contain your classes. A module also contains other data a class might rely on, such as the templates for configuration files. When you apply a class to a node, the Puppet master checks in a list of directories called a modulepath for a module directory matching the class name. The master then looks in that module’s manifests subdirectory to find the manifest containing the class definition. It reads the Puppet code contained in that class definition and uses it to compile a catalog defining a desired state for the node.
To View modulepath – puppet config print modulepath
Most modules contain a main class whose name corresponds to the name of the module itself and is kept in a special file named init.pp.
puppet parser validate à check **syntax of a manifest. The parser will return nothing if there are no errors.
puppet agent -t –noop à test run of puppet, shows what changes puppet **would have applied if it was an actual run.
Unlike the main init.pp manifest, the filename of the manifest shows us the name of the class it defines, for example, a class defined under the manifest folder of a module by cowsay::fortune, depicts that the fortune manifest is located under the manifests directory of the cowsay module. This naming pattern also helps avoid conflicts among similarly named classes provided by different modules.
New manifests created under modules can be loaded directly from the site.pp file by using an include but to maintain the simplicity it is best to include this new manifest in the init.pp file of the module itself.
Package File Service
A package resource manages the software package itself, a file resource allows you to customize a related configuration file, and a service resource starts the service provided by the software you’ve just installed and configured.
The file resource takes a source parameter, which allows you to specify a source file that will define the content of the managed file. As its value, this parameter takes a URI. While it’s possible to point to other locations, you’ll typically use this to specify a file in your module’s files directory.
A file resource can also use ‘content’ as the parameter which takes a string as a value and sets the content of the managed file to that string.
The normal form of a puppet: URI is:
puppet:///modules/<MODULE NAME>;/<FILE PATH>;
This will fetch a file from a module on the Puppet master (or from a local module when using Puppet apply). Given a modulepath of /etc/puppetlabs/code/modules, the example above would resolve to /etc/puppetlabs/code/modules/<MODULE NAME>;/files/<FILE PATH>;.
Unlike content, the source attribute can be used to recursively copy directories if the recurse attribute is set to true or remote. If a source directory contains symlinks, use the links attribute to specify whether to recreate links or follow them.
For instance, to setup a new package as a service, install the package using resource, create the configuration files using file, create the system unit file using the file resource. Then define the service resource to set the desired state of the service.
Though Puppet code will default to managing resources in the order they’re written in a manifest, we strongly recommend that you make dependencies among resources explicit through relationship metaparameters. A metaparameter is a parameter, that affects how Puppet handles a resource rather than directly defining its desired state. Relationship metaparameters tell Puppet about ordering relationships among your resources.
ð before tells Puppet that the current resource must come before the target resource. The notify metaparameter is like before, but if the target resource is a service, it has the additional effect of restarting the service whenever Puppet modifies the resource with the metaparameter set. This is useful when you need Puppet to restart a service to pick up changes in a configuration file.
The syntax for a resource reference is the capitalized resource type, followed by square brackets containing the resource title: Type[‘title’]
Variables
Variables allow a value to be bound to a name, which can then be used later in your manifest.
Assigning variable, example, $my_variables = ‘look, a string!’
Once you have defined a variable, you can use it anywhere in your manifest where you want to use the assigned value. Note that variables are parse-order dependent, which means that a variable must be defined before it can be used. Using and undefined variable will result in an undef value, which may sometimes create a valid catalog with unexpected contents.
Technically, Puppet variables are actually constants from the perspective of the Puppet parser as it parses your Puppet code to create a catalog. Once a variable is assigned, the value is fixed and cannot be changed. The variability, here, refers to the fact that a variable can have a different value set across different Puppet runs or across different systems in your infrastructure
Templates
A template is similar to a text file but offers a syntax for inserting variables as well as some more advanced language features like conditionals and iteration. This flexibility lets you manage a wide variety of file formats with a single tool.
The limitation of templates is that they’re all-or-nothing. The template must define the entire file you want to manage. If you need to manage only a single line or value in a file because another process or Puppet module will manage a different part of the file, you may want to investigate Augeas, concat, or the file_line resource type.
Puppet templating languages;
- Embedded Puppet(EPP)
- Embedded Ruby(ERB)
EPP templates have been lately introduced and provide a puppet-native templating language. An EPP template is a plain-text document interspersed with tags that allow you to customize the content.
Best practice is to begin your EPP template with a parameter tag. This declares which parameters your template will accept and allows you to set their default values. A template will work without this tag, but explicitly declaring your variables here makes the template more readable and easier to maintain.
It’s also good practice to add a comment to the beginning of the file depicting that the file is managed by Puppet.
The <%= … %>; tags are used to insert variables into a template and are called expression-printing tags. These tags insert the content of a Puppet expression, in this case the string values assigned to our variables.
Example Template:
The hyphens will prevent the creation of an empty line in the output file.
To set a file’s content with a template, Puppet’s built-in epp() function can be used to parse the EPP template file, which returns a string and the string can be passed as a value to the content parameter of the file resource.
The epp() function takes two arguments: First, a file reference in the format ‘<MODULE>;/<TEMPLATE_NAME>;’ that specifies the template file to use. Second, a hash of variable names and values to pass to the template.
Instead of putting all variables in the function declaration, we can put all the variables in a single variable which can then be passed as an argument to the epp() function.
Example:
Class Parameters
A class allows customizing all its important variables without editing the module itself with the help of class paramters. Writing parameters into a class allows you to declare that class with a set of parameter-value pairs similar to the resource declaration syntax. A class’s parameters are defined as a comma-separated list of parameter name and default value pairs ($parameter_name = default_value,). These parameter value pairs are enclosed in parentheses ((…)) between the class name and the opening curly bracket ({) that begins the body of the class. The list of parameters must be comma separated while variables set within the body of the class itself are not. This is because the Puppet parser treats these parameters as a list, while variable assignments in the body of your class are individual statements.
The include function declares a class without explicitly setting any parameter, allowing any parameters in the class to use their default values. Parameters without defaults take the special ‘undef’ value.
To declare a class with specific parameters, use the resource-like class declaration.
ð Unlike the include function, which can be used for the same class in multiple places, resource-like class declarations can only be used once per class. Because a class declared with the include uses defaults, it will always be parsed into the same set of resources in your catalog. This means that Puppet can safely handle multiple include calls for the same class. Because multiple resource-like class declarations are not guaranteed to lead to the same set of resources, Puppet has no unambiguous way to handle multiple resource-like declarations of the same class. Attempting to make multiple resource-like declarations of the same class will cause the Puppet parser to throw an error.
ð An example scenario of the above situation would be when calling/declaring classes inside the parent class itself.
Facts
The facter tool allows Puppet to automatically access information about the system where an agent is running as variables within the Puppet manifest. The Puppet agent runs facter to get a list of facts about the system to send to the Puppet master as it requests a catalog. The Puppet master then uses these facts to help compile that catalog before sending it back to the Puppet agent to be applied.
Examples:
facter -p
facter -p os
facter -p os.family
Adding the -p flag will include any custom facts that you may have installed on the Puppet master and synchronized with the agent during the pluginsync step of a Puppet run.
All facts are automatically made available within your manifests. You can access the value of any fact via the $facts hash, following the $facts[‘fact_name’] syntax. To access structured facts, you can chain more names using the same bracket indexing syntax. For example, the os.family fact you accessed above is available within a manifest as $facts[‘os’][‘family’].
Conditional Statements
A good rule of thumb is that the resource abstraction layer answers how questions, while the Puppet code itself answers what questions.
As an example, let’s take a look at the puppetlabs-apache module. While this module’s developers rely on Puppet’s providers to determine how the Apache package is installed—whether it’s handled by yum, apt-get or another package manager—Puppet doesn’t have any way of automatically determining the name of the package that needs to be installed. Depending on whether the module is used to manage Apache on a RedHat or Debian system, it will need to manage either the httpd or apache2 package.
This kind of what question is often addressed through a combination of conditional statements and facts or parameters. If you look at the puppetlabs-apache module on the Forge, you’ll see this package name and numerous other variables set based on an if statement using the osfamily fact.
In a resource declaration, the ‘name’ parameter can be explicitly defined, which makes the resource title to only serve as an internal identifier for the resource, and it doesn’t actually determine the name.
Example:
Conditional statements return different values or execute different blocks of code depending on the value of a specified variable.
Puppet supports a few different ways of implementing conditional logic:
- if statements,
- unless statements,
- case statements, and
- selectors.
An if statement includes a condition followed by a block of Puppet code that will only be executed if that condition evaluates as true. Optionally, an if statement can also include any number of elsif clauses and an else clause.
- If the if condition fails, Puppet moves on to the elsif condition (if one exists).
- If both the if and elsif conditions fail, Puppet will execute the code in the else clause (if one exists).
- If all the conditions fail, and there is no else block, Puppet will do nothing and move on.
The Forge
Installing a module means placing the module directory into the Puppet master’s modulepath.
When a module is installed, the account name is not included in the module directory name. If you aren’t aware of this, it could cause some confusion; identically named modules will conflict if you try to install them on the same master.
To see a full list of modules installed in all modulepaths on your master, use the puppet module tool’s list subcommand.
puppet module install puppetlabs-postgresql
Roles and Profiles
Component modules are designed to configure a specific piece of technology on a system. The classes these modules provide are written to be flexible. Their parameters provide an API you can use to specify precisely how you need the component technology to be configured.
A profile is a class that declares one or more related component modules and sets their parameters as needed.
A role is a class that combines one or more profiles to define the desired state for a whole system. A role should correspond to the business purpose of a server. A role itself should only compose profiles and set their parameters—it should not have any parameters itself.
Using roles and profiles is a design pattern, not something written into the Puppet source code. As far as the Puppet parser is concerned, the classes that define your roles and profiles are no different than any other class.
A role should consist of only include statements to pull in the list of profile classes that make up the role. A role should not directly declare non-profile classes or individual resources.
Efficient way to define roles and profiles;
- Create module-like directories for both roles and profiles
- inside profiles, create classes which describe a function or an app.
- for roles, include profiles.
Tip: Use regular expressions in site.pp to define the desired states for multiple machines through one node definition.
Hiera
Hiera is Puppet’s built-in data lookup system. It lets you complete this separation by moving data out of your Puppet manifests and into a separate data source. Hiera takes its name from the fact that it allows you to organize your data hierarchically. Most Hiera implementations begin with common data to set default values across your whole infrastructure and end with node-specific data needed to configure a unique system. Any data specified on the more specific level overrides the default set on the more general level. Between these most-general and most-specific levels, Hiera allows you to specify any number of intermediate levels.
The first step in implementing Hiera is to add a hiera.yaml configuration file to your environment’s code directory. This configuration file defines the levels in your hierarchy and tells Hiera where to find the data source that corresponds to each level.
When Puppet uses Hiera to look for a value, it searches according to the order of levels listed under the configuration file’s hierarchy: section.
use the built-in Hiera lookup() function to tell Puppet to fetch data for each of the component class parameters you want to manage.
Hiera is very flexible in the kinds of data sources it can use. The two most common plain-text formats for Hiera data sources are YAML and JSON, but it can be configured to use anything (such as a database or even a custom script) that can take a key as input and return a corresponding value.
Create the directory tree as defined in the hiera.yaml hierarchy;
Add specifications into files:
vim data/common.yaml
.
-–profile::pasture::app::default_message: “Baa”profile::pasture::app::sinatra_server: “thin”profile::pasture::app::default_character: “sheep”profile::pasture::app::db: “none”
vim data/domain/auroch.vm.yaml—profile::pasture::app::default_message: “Welcome to Auroch!”profile::pasture::app::db: “postgres://pasture:m00m00@pasture-db.auroch.vm/pasture”
Hiera also has an implicit data binding feature which makes direct use of fully qualified keys to set class parameters without an explicit lookup. Because this feature can make the relationship between Puppet code and Hiera data less clear, however, the lookup() function is preferred, especially when members of your team are less familiar with Hiera.) The values set at higher levels take precedence over those set in common, while the values left undefined default to those set in common.
Defined Resource Types
Puppet classes are singleton, i.e., classes in the Puppet language can only exists once within a given catalog, and writing Puppet code that declares a class twice will result in a compilation error.
A defined resource type is a block of Puppet code that can be evaluated multiple times within a single node’s catalog. Like a class, a defined resource type can take parameters and use these parameters to configure a related group of resources. Unlike a class, however, a defined resource type, is not singleton. This means that the defined resource type may be declared multiple times on the same node.
Syntax:
Declaring a defined resource type:
A resource’s title is the unique identifier Puppet uses internally to keep track of that resource. Resource relationships, for example, rely on resource titles to specify dependency relationships between resources. Resource titles are also used to log and report on resource state changes across Puppet runs.
To avoid duplicate resource errors during compilation, all resource must have a title and namevar parameter that are unique with respect to resources of the same type.
A resource’s namevar is the parameter that specifies the unique aspect on the target system that the resource manages. A resource doesn’t actually have a parameter called namevar—rather the term namevar refers to the parameter that plays this role. For example, the namevar of a file resource is its path parameter. The common convention is to use the value of a resource’s namevar as its title. To support this convention, a resource’s namevar default to the value of its title unless it is explicitly set to a different value. This is why, for instance, you generally see the filepath or package name used the title of file and package resources, and the path or name parameter left unset.
The title given to a defined resource type when it is declared is available within the defined resource type’s code block as the $title variable. By incorporating this $title variable into the titles of each resource included in the defined resource type, you can ensure that as long as the defined resource type itself is declared with a unique title, the resources it includes are also unique.
Under the hood undef is exactly what Puppet sees when it tries to evaluate a variable or parameter that has not been set. By setting it as the default for your optional parameters, you can literally pass the “undefined” state of a parameter through to the underlying user resource, which will then fall back to its default behavior for that parameter. If a variable with no value is entered, then it must be assigned a value from a source otherwise the code will fail to compile.
You can use the undef value as a default if you want to allow a parameter to remain unspecified when the defined type is declared.
Use the $title variable in constituent resource titles to ensure uniqueness.
String interpolation allows you to insert a variable into any double-quoted string. Example, “${title}@puppet.vm”.
An iterator allows you to repeat a block of Puppet code multiple times, using data from a hash or array to bind different values to the variables in the block for each iteration.
Used unnecessarily, iteration can increase your Puppet code’s complexity, making it more difficult to understand and maintain.
Control Repository
A Puppet control repository is an SCM repository containing the code and configuration that define your Puppet infrastructure. Putting your Puppet codebase into source control allows each contributor to work on a checked-out copy of the code without directly modifying anything in your master’s production modulepath. These code changes can then be reviewed and tested before being merged into the production codebase and deployed to the master’s production environment.
In a control repo, instead of the modules directory create a site directory that has only the modules managed by you. Do not include Forge modules in the control repo. External modules are generally managed by something called a Puppetfile.
When you use the Puppet Code Manager tool to deploy your control repository’s code to an environment on the master, it reads the list of external modules in your Puppetfile and automatically installs them to the environment’s modules directory. This lets easily keep your list of external module dependencies under version control without duplicating their Puppet code and managing specific code changes in your control repository.
Just be aware that because the contents of the modules directory are typically defined by a Puppetfile, your site-specific modules are kept in the distinct site directory to avoid being removed or overwritten when external modules are installed.
When you initialize a new repository, Git creates a default main branch called master. The convention for Puppet, however, is to call its main branch production. This way, the branch name matches up with the production code environment on your Puppet master.
Git Commands:
git init
git commit
git status
git add <pathname>;
git branch -m master production #rename branch to production
git remote add upstream http://localhost:3000/learning/control-repo.git
git remote -v
git push upstream production
git checkout -b <new_branch_name>; ## -b flag tells git to create a new Branch.
The Code Manager tool lets you automate the deployment of Puppet code to your master from a control repository. To configure code manager, we’ll need to set up authentication with an RSA keypair. This will allow Gitea to authenticate the Puppet master when it requests code from the control repository to deploy.
puppet code deploy production –wait
Puppetfile
A Puppetfile provides a more efficient solution for managing external module dependencies. It lets you use a single file to specify the desired version and source for each external module. Puppet’s Code Manager installs the modules specified by your Puppetfile into your environment’s modules directory during the code deployment process.
This way, you can add, remove, and update external modules by changing one or two lines of code in your Puppetfile.
Unlike the puppet module tool, Code Manager does not automatically manage dependency trees for modules, which means module dependencies on other modules will have to be resolved using any third-party tools/ or with the help of dependency tree.