Chapter 10. Monitoring, Reporting, and Troubleshooting
 | "Show me a completely smooth operation and I'll show you someone who's covering mistakes. Real boats rock." |  |
 | --Frank Herbert, Chapterhouse: Dune |
In this chapter, we will cover the following recipes:
- Noop: the don't change anything option
- Logging command output
- Logging debug messages
- Generating reports
- Producing automatic HTML documentation
- Drawing dependency graphs
- Understanding Puppet errors
- Inspecting configuration settings
Introduction
We've all had the experience of sitting in an exciting presentation about some new technology and rushing home to play with it. Of course, once you start experimenting with it, you immediately run into problems. What's going wrong? Why doesn't it work? How can I see what's happening under the hood? This chapter will help you answer some of these questions, and give you the tools to solve common Puppet problems.
We'll also see how to generate useful reports on your Puppet infrastructure and how Puppet can help you monitor and troubleshoot your network as a whole.
Noop – the don't change anything option
Sometimes your Puppet manifest doesn't do exactly what you expected, or perhaps someone else has checked in changes you didn't know about. Either way, it's good to know exactly what Puppet is going to do before it does it.
When you are retrofitting Puppet into an existing infrastructure you might not know whether Puppet is going to update a config
file or restart a production service. Any such change could result in unplanned downtime. Also, sometimes manual configuration changes are made on a server that Puppet would overwrite.
To avoid these problems, you can use Puppet's noop mode, which means no operation or do nothing. When run with the noop option, Puppet only reports what it would do but doesn't actually do anything. One caveat here is that even during a noop run, pluginsync still runs and any lib
directories in modules will be synced to nodes. This will update external fact definitions and possibly Puppet's types and providers.
How to do it...
You may run noop mode when running puppet agent
or puppet apply
by appending the --noop
switch to the command. You may also create a noop=true
line in your puppet.conf
file within the [agent]
or [main]
sections.
- Create a
noop.pp
manifest that creates a file as follows:file {'/tmp/noop': content => 'nothing', mode => 0644, }
- Now run puppet agent with the
noop
switch:t@mylaptop ~/puppet/manifests $ puppet apply noop.pp --noop Notice: Compiled catalog for mylaptop in environment production in 0.41 seconds Notice: /Stage[main]/Main/File[/tmp/noop]/ensure: current_value absent, should be file (noop) Notice: Class[Main]: Would have triggered 'refresh' from 1 events Notice: Stage[main]: Would have triggered 'refresh' from 1 events Notice: Finished catalog run in 0.02 seconds
- Now run without the
noop
option to see that the file is created:t@mylaptop ~/puppet/manifests $ puppet apply noop.pp Notice: Compiled catalog for mylaptop in environment production in 0.37 seconds Notice: /Stage[main]/Main/File[/tmp/noop]/ensure: defined content as '{md5}3e47b75000b0924b6c9ba5759a7cf15d'
How it works...
In the noop
mode, Puppet does everything it would normally, with the exception of actually making any changes to the machine (the exec
resources, for example, won't run). It tells you what it would have done, and you can compare this with what you expected to happen. If there are any differences, double-check the manifest or the current state of the machine.
Note
Note that when we ran with --noop
, Puppet warned us that it would have created the /tmp/noop
file. This may or may not be what we want, but it's useful to know in advance. If you are making changes to the code applied to your production servers, it's useful to run puppet agent with the --noop
option to ensure that your changes will not affect the production services.
There's more...
You can also use noop mode as a simple auditing tool. It will tell you whether any changes have been made to the machine since Puppet last applied its manifest. Some organizations require all config changes to be made with Puppet, which is one way of implementing a change control process. Unauthorized changes to the resources managed by Puppet can be detected using Puppet in noop mode and you can then decide whether to merge the changes back into the Puppet manifest or undo them.
You can also use the --debug
switch when running puppet agent to see the details of every change Puppet makes during an agent run. This can be helpful when trying to figure out how Puppet is applying certain exec resources or to see in what order things are happening.
If you are running a master, you can compile the catalog for a node on the master with the --trace
option in addition to --debug
. If the catalog is failing to compile, this method will also fail to compile the catalog (if you have an old definition for the cookbook node that is failing, try commenting it out before running this test). This produces a lot of debugging output. For example, to compile the catalog for our cookbook host on our master and place the results into /tmp/cookbook.log
:
root@puppet: ~#puppet master --compile cookbook.example.com --debug --trace --logdest /tmp/cookbook.log
Debug: Executing '/etc/puppet/cookbook.sh cookbook.example.com'
Debug: Using cached facts for cookbook.example.com
Info: Caching node for cookbook.example.com
Debug: importing '/etc/puppet/environments/production/modules/enc/manifests/init.pp' in environment production
Debug: Automatically imported enc from enc into production
Notice: Compiled catalog for cookbook.example.com in environment production in 0.09 seconds
Info: Caching catalog for cookbook.example.com
Debug: Configuring PuppetDB terminuses with config file /etc/puppet/puppetdb.conf
Debug: Using cached certificate for ca
Debug: Using cached certificate for puppet
Debug: Using cached certificate_revocation_list for ca
Info: 'replace catalog' command for cookbook.example.com submitted to PuppetDB with UUIDe2a655ca-bd81-4428-b70a-a3a76c5f15d1
{
"metadata": {
"api_version": 1
},
"data": {
"edges": [
{
"target": "Class[main]",
"source": "Stage[main]"
...
Note
After compiling the catalog, Puppet will print out the catalog to the command line. The log file (/tmp/cookbook.log
) will have a lot of information on how the catalog was compiled.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
- The Automatic syntax checking with Git hooks recipe in Chapter 2, Puppet Infrastructure
- The Generating reports recipe in this chapter
- The Testing your Puppet manifests with rspec-puppet recipe in Chapter 9, External Tools and the Puppet Ecosystem
noop mode when running puppet agent
or puppet apply
by appending the --noop
switch to the command. You may also create a noop=true
line in your puppet.conf
file within the [agent]
or [main]
sections.
- Create a
noop.pp
manifest that creates a file as follows:file {'/tmp/noop': content => 'nothing', mode => 0644, }
- Now run puppet agent with the
noop
switch:t@mylaptop ~/puppet/manifests $ puppet apply noop.pp --noop Notice: Compiled catalog for mylaptop in environment production in 0.41 seconds Notice: /Stage[main]/Main/File[/tmp/noop]/ensure: current_value absent, should be file (noop) Notice: Class[Main]: Would have triggered 'refresh' from 1 events Notice: Stage[main]: Would have triggered 'refresh' from 1 events Notice: Finished catalog run in 0.02 seconds
- Now run without the
noop
option to see that the file is created:t@mylaptop ~/puppet/manifests $ puppet apply noop.pp Notice: Compiled catalog for mylaptop in environment production in 0.37 seconds Notice: /Stage[main]/Main/File[/tmp/noop]/ensure: defined content as '{md5}3e47b75000b0924b6c9ba5759a7cf15d'
How it works...
In the noop
mode, Puppet does everything it would normally, with the exception of actually making any changes to the machine (the exec
resources, for example, won't run). It tells you what it would have done, and you can compare this with what you expected to happen. If there are any differences, double-check the manifest or the current state of the machine.
Note
Note that when we ran with --noop
, Puppet warned us that it would have created the /tmp/noop
file. This may or may not be what we want, but it's useful to know in advance. If you are making changes to the code applied to your production servers, it's useful to run puppet agent with the --noop
option to ensure that your changes will not affect the production services.
There's more...
You can also use noop mode as a simple auditing tool. It will tell you whether any changes have been made to the machine since Puppet last applied its manifest. Some organizations require all config changes to be made with Puppet, which is one way of implementing a change control process. Unauthorized changes to the resources managed by Puppet can be detected using Puppet in noop mode and you can then decide whether to merge the changes back into the Puppet manifest or undo them.
You can also use the --debug
switch when running puppet agent to see the details of every change Puppet makes during an agent run. This can be helpful when trying to figure out how Puppet is applying certain exec resources or to see in what order things are happening.
If you are running a master, you can compile the catalog for a node on the master with the --trace
option in addition to --debug
. If the catalog is failing to compile, this method will also fail to compile the catalog (if you have an old definition for the cookbook node that is failing, try commenting it out before running this test). This produces a lot of debugging output. For example, to compile the catalog for our cookbook host on our master and place the results into /tmp/cookbook.log
:
root@puppet: ~#puppet master --compile cookbook.example.com --debug --trace --logdest /tmp/cookbook.log
Debug: Executing '/etc/puppet/cookbook.sh cookbook.example.com'
Debug: Using cached facts for cookbook.example.com
Info: Caching node for cookbook.example.com
Debug: importing '/etc/puppet/environments/production/modules/enc/manifests/init.pp' in environment production
Debug: Automatically imported enc from enc into production
Notice: Compiled catalog for cookbook.example.com in environment production in 0.09 seconds
Info: Caching catalog for cookbook.example.com
Debug: Configuring PuppetDB terminuses with config file /etc/puppet/puppetdb.conf
Debug: Using cached certificate for ca
Debug: Using cached certificate for puppet
Debug: Using cached certificate_revocation_list for ca
Info: 'replace catalog' command for cookbook.example.com submitted to PuppetDB with UUIDe2a655ca-bd81-4428-b70a-a3a76c5f15d1
{
"metadata": {
"api_version": 1
},
"data": {
"edges": [
{
"target": "Class[main]",
"source": "Stage[main]"
...
Note
After compiling the catalog, Puppet will print out the catalog to the command line. The log file (/tmp/cookbook.log
) will have a lot of information on how the catalog was compiled.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
- The Automatic syntax checking with Git hooks recipe in Chapter 2, Puppet Infrastructure
- The Generating reports recipe in this chapter
- The Testing your Puppet manifests with rspec-puppet recipe in Chapter 9, External Tools and the Puppet Ecosystem
noop
mode, Puppet
does everything it would normally, with the exception of actually making any changes to the machine (the exec
resources, for example, won't run). It tells you what it would have done, and you can compare this with what you expected to happen. If there are any differences, double-check the manifest or the current state of the machine.
Note
Note that when we ran with --noop
, Puppet warned us that it would have created the /tmp/noop
file. This may or may not be what we want, but it's useful to know in advance. If you are making changes to the code applied to your production servers, it's useful to run puppet agent with the --noop
option to ensure that your changes will not affect the production services.
There's more...
You can also use noop mode as a simple auditing tool. It will tell you whether any changes have been made to the machine since Puppet last applied its manifest. Some organizations require all config changes to be made with Puppet, which is one way of implementing a change control process. Unauthorized changes to the resources managed by Puppet can be detected using Puppet in noop mode and you can then decide whether to merge the changes back into the Puppet manifest or undo them.
You can also use the --debug
switch when running puppet agent to see the details of every change Puppet makes during an agent run. This can be helpful when trying to figure out how Puppet is applying certain exec resources or to see in what order things are happening.
If you are running a master, you can compile the catalog for a node on the master with the --trace
option in addition to --debug
. If the catalog is failing to compile, this method will also fail to compile the catalog (if you have an old definition for the cookbook node that is failing, try commenting it out before running this test). This produces a lot of debugging output. For example, to compile the catalog for our cookbook host on our master and place the results into /tmp/cookbook.log
:
root@puppet: ~#puppet master --compile cookbook.example.com --debug --trace --logdest /tmp/cookbook.log
Debug: Executing '/etc/puppet/cookbook.sh cookbook.example.com'
Debug: Using cached facts for cookbook.example.com
Info: Caching node for cookbook.example.com
Debug: importing '/etc/puppet/environments/production/modules/enc/manifests/init.pp' in environment production
Debug: Automatically imported enc from enc into production
Notice: Compiled catalog for cookbook.example.com in environment production in 0.09 seconds
Info: Caching catalog for cookbook.example.com
Debug: Configuring PuppetDB terminuses with config file /etc/puppet/puppetdb.conf
Debug: Using cached certificate for ca
Debug: Using cached certificate for puppet
Debug: Using cached certificate_revocation_list for ca
Info: 'replace catalog' command for cookbook.example.com submitted to PuppetDB with UUIDe2a655ca-bd81-4428-b70a-a3a76c5f15d1
{
"metadata": {
"api_version": 1
},
"data": {
"edges": [
{
"target": "Class[main]",
"source": "Stage[main]"
...
Note
After compiling the catalog, Puppet will print out the catalog to the command line. The log file (/tmp/cookbook.log
) will have a lot of information on how the catalog was compiled.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
- The Automatic syntax checking with Git hooks recipe in Chapter 2, Puppet Infrastructure
- The Generating reports recipe in this chapter
- The Testing your Puppet manifests with rspec-puppet recipe in Chapter 9, External Tools and the Puppet Ecosystem
simple auditing tool. It will tell you whether any changes have been made to the machine since Puppet last applied its manifest. Some organizations require all config changes to be made with Puppet, which is one way of implementing a change control process. Unauthorized changes to the resources managed by Puppet can be detected using Puppet in noop mode and you can then decide whether to merge the changes back into the Puppet manifest or undo them.
You can also use the --debug
switch when running puppet agent to see the details of every change Puppet makes during an agent run. This can be helpful when trying to figure out how Puppet is applying certain exec resources or to see in what order things are happening.
If you are running a master, you can compile the catalog for a node on the master with the --trace
option in addition to --debug
. If the catalog is failing to compile, this method will also fail to compile the catalog (if you have an old definition for the cookbook node that is failing, try commenting it out before running this test). This produces a lot of debugging output. For example, to compile the catalog for our cookbook host on our master and place the results into /tmp/cookbook.log
:
root@puppet: ~#puppet master --compile cookbook.example.com --debug --trace --logdest /tmp/cookbook.log
Debug: Executing '/etc/puppet/cookbook.sh cookbook.example.com'
Debug: Using cached facts for cookbook.example.com
Info: Caching node for cookbook.example.com
Debug: importing '/etc/puppet/environments/production/modules/enc/manifests/init.pp' in environment production
Debug: Automatically imported enc from enc into production
Notice: Compiled catalog for cookbook.example.com in environment production in 0.09 seconds
Info: Caching catalog for cookbook.example.com
Debug: Configuring PuppetDB terminuses with config file /etc/puppet/puppetdb.conf
Debug: Using cached certificate for ca
Debug: Using cached certificate for puppet
Debug: Using cached certificate_revocation_list for ca
Info: 'replace catalog' command for cookbook.example.com submitted to PuppetDB with UUIDe2a655ca-bd81-4428-b70a-a3a76c5f15d1
{
"metadata": {
"api_version": 1
},
"data": {
"edges": [
{
"target": "Class[main]",
"source": "Stage[main]"
...
Note
After compiling the catalog, Puppet will print out the catalog to the command line. The log file (/tmp/cookbook.log
) will have a lot of information on how the catalog was compiled.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
- The Automatic syntax checking with Git hooks recipe in Chapter 2, Puppet Infrastructure
- The Generating reports recipe in this chapter
- The Testing your Puppet manifests with rspec-puppet recipe in Chapter 9, External Tools and the Puppet Ecosystem
- Chapter 6, Managing Resources and Files
- The Automatic syntax checking with Git hooks recipe in Chapter 2, Puppet Infrastructure
- The Generating reports recipe in this chapter
- The Testing your Puppet manifests with rspec-puppet recipe in Chapter 9, External Tools and the Puppet Ecosystem
Logging command output
When you use the exec
resources to run commands on the node, Puppet will give you an error message such as the following if a command returns a non-zero exit status:
Notice: /Stage[main]/Main/Exec[/bin/cat /tmp/missing]/returns: /bin/cat: /tmp/missing: No such file or directory
Error: /bin/cat /tmp/missing returned 1 instead of one of [0]
Error: /Stage[main]/Main/Exec[/bin/cat /tmp/missing]/returns: change from notrun to 0 failed: /bin/cat /tmp/missing returned 1 instead of one of [0]
As you can see, Puppet not only reports that the command failed, but shows its output:
/bin/cat: /tmp/missing: No such file or directory
This is useful to figure out why the command didn't work, but sometimes the command actually succeeds (in that it returns a zero exit status) but still doesn't do what we wanted. In that case, how can you see the command output? You can use the logoutput
attribute.
How to do it...
Follow these steps in order to log command output:
- Define an
exec
resource with thelogoutput
parameter as shown in the following code snippet:exec { 'exec with output': command => '/bin/cat /etc/hostname', logoutput => true, }
- Run Puppet:
t@mylaptop ~/puppet/manifests $ puppet apply exec.pp Notice: Compiled catalog for mylaptop in environment production in 0.46 seconds Notice: /Stage[main]/Main/Exec[exec with outout]/returns: mylaptop Notice: /Stage[main]/Main/Exec[exec with outout]/returns: executed successfully Notice: Finished catalog run in 0.06 seconds
- As you can see, even though the command succeeds, Puppet prints the output:
mylaptop
How it works...
The logoutput
attribute has three possible settings:
false
: This never prints the command outputon_failure
: This only prints the output if the command fails (the default setting)true
: This always prints the output, whether the command succeeds or fails
There's more...
You can set the default value of logoutput
to always display command output for all exec
resources by defining the following in your site.pp
file:
Exec {
logoutput => true,
Note
Resource defaults: What's this Exec syntax? It looks like an exec
resource, but it's not. When you use Exec
with a capital E, you're setting the resource default for exec. You may set the resource default for any resource by capitalizing the first letter of the resource type. Anywhere that Puppet see's that resource within the current scope or a nested subscope, it will apply the defaults you define.
If you never want to see the command output, whether it succeeds or fails, use:
logoutput => false,
More information is available at https://docs.puppetlabs.com/references/latest/type.html#exec.
exec
resource with the logoutput
parameter as shown in the following code snippet:exec { 'exec with output': command => '/bin/cat /etc/hostname', logoutput => true, }
t@mylaptop ~/puppet/manifests $ puppet apply exec.pp Notice: Compiled catalog for mylaptop in environment production in 0.46 seconds Notice: /Stage[main]/Main/Exec[exec with outout]/returns: mylaptop Notice: /Stage[main]/Main/Exec[exec with outout]/returns: executed successfully Notice: Finished catalog run in 0.06 seconds
mylaptop
How it works...
The logoutput
attribute has three possible settings:
false
: This never prints the command outputon_failure
: This only prints the output if the command fails (the default setting)true
: This always prints the output, whether the command succeeds or fails
There's more...
You can set the default value of logoutput
to always display command output for all exec
resources by defining the following in your site.pp
file:
Exec {
logoutput => true,
Note
Resource defaults: What's this Exec syntax? It looks like an exec
resource, but it's not. When you use Exec
with a capital E, you're setting the resource default for exec. You may set the resource default for any resource by capitalizing the first letter of the resource type. Anywhere that Puppet see's that resource within the current scope or a nested subscope, it will apply the defaults you define.
If you never want to see the command output, whether it succeeds or fails, use:
logoutput => false,
More information is available at https://docs.puppetlabs.com/references/latest/type.html#exec.
logoutput
attribute has three possible settings:
false
: This never
- prints the command output
on_failure
: This only prints the output if the command fails (the default setting)true
: This always prints the output, whether the command succeeds or fails
There's more...
You can set the default value of logoutput
to always display command output for all exec
resources by defining the following in your site.pp
file:
Exec {
logoutput => true,
Note
Resource defaults: What's this Exec syntax? It looks like an exec
resource, but it's not. When you use Exec
with a capital E, you're setting the resource default for exec. You may set the resource default for any resource by capitalizing the first letter of the resource type. Anywhere that Puppet see's that resource within the current scope or a nested subscope, it will apply the defaults you define.
If you never want to see the command output, whether it succeeds or fails, use:
logoutput => false,
More information is available at https://docs.puppetlabs.com/references/latest/type.html#exec.
logoutput
to always display command output for all exec
resources by defining the following in your site.pp
file:
Note
Resource defaults: What's this Exec syntax? It looks like an exec
resource, but it's not. When you use Exec
with a capital E, you're setting the resource default for exec. You may set the resource default for any resource by capitalizing the first letter of the resource type. Anywhere that Puppet see's that resource within the current scope or a nested subscope, it will apply the defaults you define.
If you never want to see the command output, whether it succeeds or fails, use:
logoutput => false,
More information is available at https://docs.puppetlabs.com/references/latest/type.html#exec.
Logging debug messages
It can be very helpful when debugging problems if you can print out information at a certain point in the manifest. This is a good way to tell, for example, if a variable isn't defined or has an unexpected value. Sometimes it's useful just to know that a particular piece of code has been run. Puppet's notify
resource lets you print out such messages.
How to do it...
Define a notify
resource in your manifest at the point you want to investigate:
notify { 'Got this far!': }
How it works...
When this resource is applied, Puppet will print out the message:
notice: Got this far!
There's more...
In addition to simple messages, we can output variables within our notify
statements. Additionally, we can treat the notify
calls the same as other resources, having them require or be required by other resources.
Printing out variable values
You can refer to variables in the message:
notify { "operatingsystem is ${::operatingsystem}": }
Puppet will interpolate the values in the printout:
Notice: operatingsystem is Fedora
The double colon (::
) before the fact name tells Puppet that this is a variable in top scope (accessible to all classes) and not local to the class. For more about how Puppet handles variable scope, see the Puppet Labs article:
Resource ordering
Puppet compiles your manifests into a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
notify
resource in your manifest at the point you want to investigate:
How it works...
When this resource is applied, Puppet will print out the message:
notice: Got this far!
There's more...
In addition to simple messages, we can output variables within our notify
statements. Additionally, we can treat the notify
calls the same as other resources, having them require or be required by other resources.
Printing out variable values
You can refer to variables in the message:
notify { "operatingsystem is ${::operatingsystem}": }
Puppet will interpolate the values in the printout:
Notice: operatingsystem is Fedora
The double colon (::
) before the fact name tells Puppet that this is a variable in top scope (accessible to all classes) and not local to the class. For more about how Puppet handles variable scope, see the Puppet Labs article:
Resource ordering
Puppet compiles your manifests into a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
applied, Puppet will print out the message:
notice: Got this far!
There's more...
In addition to simple messages, we can output variables within our notify
statements. Additionally, we can treat the notify
calls the same as other resources, having them require or be required by other resources.
Printing out variable values
You can refer to variables in the message:
notify { "operatingsystem is ${::operatingsystem}": }
Puppet will interpolate the values in the printout:
Notice: operatingsystem is Fedora
The double colon (::
) before the fact name tells Puppet that this is a variable in top scope (accessible to all classes) and not local to the class. For more about how Puppet handles variable scope, see the Puppet Labs article:
Resource ordering
Puppet compiles your manifests into a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
notify
statements. Additionally, we can treat the notify
calls the same as other resources, having them require or be required by other resources.
Printing out variable values
You can refer to variables in the message:
notify { "operatingsystem is ${::operatingsystem}": }
Puppet will interpolate the values in the printout:
Notice: operatingsystem is Fedora
The double colon (::
) before the fact name tells Puppet that this is a variable in top scope (accessible to all classes) and not local to the class. For more about how Puppet handles variable scope, see the Puppet Labs article:
Resource ordering
Puppet compiles your manifests into a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
variables in the message:
notify { "operatingsystem is ${::operatingsystem}": }
Puppet will interpolate the values in the printout:
Notice: operatingsystem is Fedora
The double colon (::
) before the fact name tells Puppet that this is a variable in top scope (accessible to all classes) and not local to the class. For more about how Puppet handles variable scope, see the Puppet Labs article:
Resource ordering
Puppet compiles your manifests into a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
a catalog; the order in which resources are executed on the client (node) may not be the same as the order of the resources within your source files. When you are using a notify
resource for debugging, you should use resource chaining to ensure that the notify resource
is executed before or after your failing resource.
For example, if the exec failing exec
is failing, you can chain a notify resource
to run directly before the failed exec resource as shown here:
notify{"failed exec on ${hostname}": }->
exec {'failing exec':
command => "/bin/grep ${hostname} /etc/hosts",
logoutput => true,
}
If you don't chain the resource or use a metaparameter such as before
or require
, there is no guarantee your notify
statement will be executed near the other resources you are interested in debugging. More information on resource ordering can be found at https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html.
For example, to have your notify resource
run after 'failing exec'
in the preceding code snippet, use:
notify { 'Resource X has been applied': require => Exec['failing exec'], }
Note, however, that in this case the notify resource
will fail to execute since the exec failed. When a resource fails, all the resources that depended on that resource are skipped:
notify {'failed exec failed': require => Exec['failing exec'] }
When we run Puppet, we see that the notify resource
is skipped:
t@mylaptop ~/puppet/manifests $ puppet apply fail.pp ... Error: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Error: /Stage[main]/Main/Exec[failing exec]/returns: change from notrun to 0 failed: /bin/grepmylaptop /etc/hosts returned 1 instead of one of [0] Notice: /Stage[main]/Main/Notify[failed exec failed]: Dependency Exec[failing exec] has failures: true Warning: /Stage[main]/Main/Notify[failed exec failed]: Skipping because of failed dependencies Notice: Finished catalog run in 0.06 seconds
Generating reports
If you're managing a lot of machines, Puppet's reporting facility can give you some valuable information on what's actually happening out there.
How to do it...
To enable reports, just add this to a client's puppet.conf
: within the [main]
or [agent]
sections:
report = true
Tip
In recent versions (greater than 3.0) of Puppet, report = true
is the default setting.
How it works...
With reporting enabled, Puppet will generate a report file, containing data such as:
- Date and time of the run
- Total time for the run
- Log messages output during the run
- List of all the resources in the client's manifest
- Whether Puppet changed any resources, and how many
- Whether the run succeeded or failed
By default, these reports are stored on the node at /var/lib/puppet/reports
in a directory named after the hostname, but you can specify a different destination using the reportdir
option. You can create your own scripts to process these reports (which are in the standard YAML format). When we run puppet agent on cookbook.example.com
, the following file is created on the master:
/var/lib/puppet/reports/cookbook.example.com/201411230717.yaml
There's more...
If you have more than one master server, you can have all your reports sent to the same server by specifying report_server
in the [agent]
section of puppet.conf
.
If you just want one report, or you don't want to enable reporting all the time, you can add the --report
switch to the command line when you run Puppet agent manually:
[root@cookbook ~]# puppet agent -t --report
Notice: Finished catalog run in 0.34 seconds
You won't see any additional output, but a report file will be generated in the report
directory.
You can also see some overall statistics about a Puppet run by supplying the --summarize
switch:
[root@cookbook ~]# puppet agent -t --report --summarize
Notice: Finished catalog run in 0.35 seconds
Changes:
Total: 2
Events:
Total: 2
Success: 2
Resources:
Total: 10
Changed: 2
Out of sync: 2
Time:
Filebucket: 0.00
Schedule: 0.00
Notify: 0.00
Config retrieval: 0.94
Total: 0.95
Last run: 1416727357
Version:
Config: 1416727291
Puppet: 3.7.3
Other report types
Puppet can generate different types of reports with the reports option in the [main]
or [master]
section of puppet.conf
on your Puppet master servers. There are several built-in report types listed at https://docs.puppetlabs.com/references/latest/report.html. In addition to the built-in report types, there are some community developed reports that are quite useful. The Foreman (http://theforeman.org), for example, provides a Foreman report type that you can enable to forward your node reports to the Foreman.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
puppet.conf
: within the [main]
or [agent]
sections:
Tip
In recent versions (greater than 3.0) of Puppet, report = true
is the default setting.
How it works...
With reporting enabled, Puppet will generate a report file, containing data such as:
- Date and time of the run
- Total time for the run
- Log messages output during the run
- List of all the resources in the client's manifest
- Whether Puppet changed any resources, and how many
- Whether the run succeeded or failed
By default, these reports are stored on the node at /var/lib/puppet/reports
in a directory named after the hostname, but you can specify a different destination using the reportdir
option. You can create your own scripts to process these reports (which are in the standard YAML format). When we run puppet agent on cookbook.example.com
, the following file is created on the master:
/var/lib/puppet/reports/cookbook.example.com/201411230717.yaml
There's more...
If you have more than one master server, you can have all your reports sent to the same server by specifying report_server
in the [agent]
section of puppet.conf
.
If you just want one report, or you don't want to enable reporting all the time, you can add the --report
switch to the command line when you run Puppet agent manually:
[root@cookbook ~]# puppet agent -t --report
Notice: Finished catalog run in 0.34 seconds
You won't see any additional output, but a report file will be generated in the report
directory.
You can also see some overall statistics about a Puppet run by supplying the --summarize
switch:
[root@cookbook ~]# puppet agent -t --report --summarize
Notice: Finished catalog run in 0.35 seconds
Changes:
Total: 2
Events:
Total: 2
Success: 2
Resources:
Total: 10
Changed: 2
Out of sync: 2
Time:
Filebucket: 0.00
Schedule: 0.00
Notify: 0.00
Config retrieval: 0.94
Total: 0.95
Last run: 1416727357
Version:
Config: 1416727291
Puppet: 3.7.3
Other report types
Puppet can generate different types of reports with the reports option in the [main]
or [master]
section of puppet.conf
on your Puppet master servers. There are several built-in report types listed at https://docs.puppetlabs.com/references/latest/report.html. In addition to the built-in report types, there are some community developed reports that are quite useful. The Foreman (http://theforeman.org), for example, provides a Foreman report type that you can enable to forward your node reports to the Foreman.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
are stored on the node at /var/lib/puppet/reports
in a directory named after the hostname, but you can specify a different destination using the reportdir
option. You can create your own scripts to process these reports (which are in the standard YAML format). When we run puppet agent on cookbook.example.com
, the following file is created on the master:
/var/lib/puppet/reports/cookbook.example.com/201411230717.yaml
There's more...
If you have more than one master server, you can have all your reports sent to the same server by specifying report_server
in the [agent]
section of puppet.conf
.
If you just want one report, or you don't want to enable reporting all the time, you can add the --report
switch to the command line when you run Puppet agent manually:
[root@cookbook ~]# puppet agent -t --report
Notice: Finished catalog run in 0.34 seconds
You won't see any additional output, but a report file will be generated in the report
directory.
You can also see some overall statistics about a Puppet run by supplying the --summarize
switch:
[root@cookbook ~]# puppet agent -t --report --summarize
Notice: Finished catalog run in 0.35 seconds
Changes:
Total: 2
Events:
Total: 2
Success: 2
Resources:
Total: 10
Changed: 2
Out of sync: 2
Time:
Filebucket: 0.00
Schedule: 0.00
Notify: 0.00
Config retrieval: 0.94
Total: 0.95
Last run: 1416727357
Version:
Config: 1416727291
Puppet: 3.7.3
Other report types
Puppet can generate different types of reports with the reports option in the [main]
or [master]
section of puppet.conf
on your Puppet master servers. There are several built-in report types listed at https://docs.puppetlabs.com/references/latest/report.html. In addition to the built-in report types, there are some community developed reports that are quite useful. The Foreman (http://theforeman.org), for example, provides a Foreman report type that you can enable to forward your node reports to the Foreman.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
report_server
in the [agent]
section of puppet.conf
.
--report
switch to the command line when you run Puppet agent manually:
report
directory.
--summarize
switch:
Other report types
Puppet can generate different types of reports with the reports option in the [main]
or [master]
section of puppet.conf
on your Puppet master servers. There are several built-in report types listed at https://docs.puppetlabs.com/references/latest/report.html. In addition to the built-in report types, there are some community developed reports that are quite useful. The Foreman (http://theforeman.org), for example, provides a Foreman report type that you can enable to forward your node reports to the Foreman.
See also
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
[main]
or [master]
section of puppet.conf
on your Puppet master servers. There are several built-in report types
listed at https://docs.puppetlabs.com/references/latest/report.html. In addition to the built-in report types, there are some community developed reports that are quite useful. The Foreman (http://theforeman.org), for example, provides a Foreman report type that you can enable to forward your node reports to the Foreman.
- The Auditing resources recipe in Chapter 6, Managing Resources and Files
- Chapter 6, Managing Resources and Files
Producing automatic HTML documentation
As your manifests get bigger and more complex, it can be helpful to create HTML documentation for your nodes and classes using Puppet's automatic documentation tool, puppet doc
.
How to do it...
Follow these steps to generate HTML documentation for your manifest:
- Run the following command:
t@mylaptop ~/puppet $ puppet doc --all --outputdir=/tmp/puppet --mode rdoc --modulepath=modules/
- This will generate a set of HTML files at
/tmp/puppet
. Open the top-levelindex.html
file with your web browser (file:///tmp/puppet/index.html
), and you'll see something like the following screenshot: - Click the classes link on the left and select the Apache module, something similar to the following will be displayed:
How it works...
The puppet doc
command creates a structured HTML documentation tree similar to that produced by RDoc, the popular Ruby documentation generator. This makes it easier to understand how different parts of the manifest relate to one another.
There's more...
The puppet doc
command will generate basic documentation of your manifests as they stand, but you can include more useful information by adding comments to your manifest files, using the standard RDoc syntax. When we created our base class using puppet module generate, these comments were created for us:
# == Class: base
#
# Full description of class base here.
#
# === Parameters
#
# Document parameters here.
#
# [*sample_parameter*]
# Explanation of what this parameter affects and what it defaults to.
# e.g. "Specify one or more upstream ntp servers as an array."
#
# === Variables
#
# Here you should define a list of variables that this module would require.
#
# [*sample_variable*]
# Explanation of how this variable affects the funtion of this class and if
# it has a default. e.g. "The parameter enc_ntp_servers must be set by the
# External Node Classifier as a comma separated list of hostnames." (Note,
# global variables should be avoided in favor of class parameters as
# of Puppet 2.6.)
#
# === Examples
#
# class { base:
# servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
# }
#
# === Authors
#
# Author Name <author@domain.com>
#
# === Copyright
#
# Copyright 2014 Your name here, unless otherwise noted.
#
class base {
After generating the HTML documentation, we can see the result for the base module as shown in the following screenshot:
HTML documentation for your manifest:
- Run the following command:
t@mylaptop ~/puppet $ puppet doc --all --outputdir=/tmp/puppet --mode rdoc --modulepath=modules/
- This will generate a set of HTML files at
/tmp/puppet
. Open the top-levelindex.html
file with your web browser (file:///tmp/puppet/index.html
), and you'll see something like the following screenshot: - Click the classes link on the left and select the Apache module, something similar to the following will be displayed:
How it works...
The puppet doc
command creates a structured HTML documentation tree similar to that produced by RDoc, the popular Ruby documentation generator. This makes it easier to understand how different parts of the manifest relate to one another.
There's more...
The puppet doc
command will generate basic documentation of your manifests as they stand, but you can include more useful information by adding comments to your manifest files, using the standard RDoc syntax. When we created our base class using puppet module generate, these comments were created for us:
# == Class: base
#
# Full description of class base here.
#
# === Parameters
#
# Document parameters here.
#
# [*sample_parameter*]
# Explanation of what this parameter affects and what it defaults to.
# e.g. "Specify one or more upstream ntp servers as an array."
#
# === Variables
#
# Here you should define a list of variables that this module would require.
#
# [*sample_variable*]
# Explanation of how this variable affects the funtion of this class and if
# it has a default. e.g. "The parameter enc_ntp_servers must be set by the
# External Node Classifier as a comma separated list of hostnames." (Note,
# global variables should be avoided in favor of class parameters as
# of Puppet 2.6.)
#
# === Examples
#
# class { base:
# servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
# }
#
# === Authors
#
# Author Name <author@domain.com>
#
# === Copyright
#
# Copyright 2014 Your name here, unless otherwise noted.
#
class base {
After generating the HTML documentation, we can see the result for the base module as shown in the following screenshot:
puppet doc
command
creates a structured HTML documentation tree similar to that produced by RDoc, the popular Ruby documentation generator. This makes it easier to understand how different parts of the manifest relate to one another.
There's more...
The puppet doc
command will generate basic documentation of your manifests as they stand, but you can include more useful information by adding comments to your manifest files, using the standard RDoc syntax. When we created our base class using puppet module generate, these comments were created for us:
# == Class: base
#
# Full description of class base here.
#
# === Parameters
#
# Document parameters here.
#
# [*sample_parameter*]
# Explanation of what this parameter affects and what it defaults to.
# e.g. "Specify one or more upstream ntp servers as an array."
#
# === Variables
#
# Here you should define a list of variables that this module would require.
#
# [*sample_variable*]
# Explanation of how this variable affects the funtion of this class and if
# it has a default. e.g. "The parameter enc_ntp_servers must be set by the
# External Node Classifier as a comma separated list of hostnames." (Note,
# global variables should be avoided in favor of class parameters as
# of Puppet 2.6.)
#
# === Examples
#
# class { base:
# servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
# }
#
# === Authors
#
# Author Name <author@domain.com>
#
# === Copyright
#
# Copyright 2014 Your name here, unless otherwise noted.
#
class base {
After generating the HTML documentation, we can see the result for the base module as shown in the following screenshot:
puppet doc
command will
generate basic documentation of your manifests as they stand, but you can include more useful information by adding comments to your manifest files, using the standard RDoc syntax. When we created our base class using puppet module generate, these comments were created for us:
# == Class: base
#
# Full description of class base here.
#
# === Parameters
#
# Document parameters here.
#
# [*sample_parameter*]
# Explanation of what this parameter affects and what it defaults to.
# e.g. "Specify one or more upstream ntp servers as an array."
#
# === Variables
#
# Here you should define a list of variables that this module would require.
#
# [*sample_variable*]
# Explanation of how this variable affects the funtion of this class and if
# it has a default. e.g. "The parameter enc_ntp_servers must be set by the
# External Node Classifier as a comma separated list of hostnames." (Note,
# global variables should be avoided in favor of class parameters as
# of Puppet 2.6.)
#
# === Examples
#
# class { base:
# servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
# }
#
# === Authors
#
# Author Name <author@domain.com>
#
# === Copyright
#
# Copyright 2014 Your name here, unless otherwise noted.
#
class base {
After generating the HTML documentation, we can see the result for the base module as shown in the following screenshot:
Drawing dependency graphs
Dependencies can get complicated quickly, and it's easy to end up with a circular dependency (where A depends on B, which depends on A) that will cause Puppet to complain and stop working. Fortunately, Puppet's --graph
option makes it easy to generate a diagram of your resources and the dependencies between them, which can be a big help in fixing such problems.
Getting ready
Install the graphviz
package to view the diagram files:
t@mylaptop ~ $ sudo puppet resource package graphviz ensure=installed
Notice: /Package[graphviz]/ensure: created
package { 'graphviz':
ensure => '2.34.0-9.fc20',
}
How to do it...
Follow these steps to generate a dependency graph for your manifest:
- Create the directories for a new
trifecta
module:ubuntu@cookbook:~/puppet$ mkdir modules/trifecta ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/manifests ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/files
- Create the file
modules/trifecta/manifests/init.pp
with the following code containing a deliberate circular dependency (can you spot it?):class trifecta { package { 'ntp': ensure => installed, require => File['/etc/ntp.conf'], } service { 'ntp': ensure => running, require => Package['ntp'], } file { '/etc/ntp.conf': source => 'puppet:///modules/trifecta/ntp.conf', notify => Service['ntp'], require => Package['ntp'], } }
- Create a simple
ntp.conf
file:t@mylaptop~/puppet $ cd modules/trifecta/files t@mylaptop~/puppet/modules/trifecta/files $ echo "server 127.0.0.1" >ntp.conf
- Since we'll be working locally on this problem, create a
trifecta.pp
manifest that includes the broken trifecta class:include trifecta
- Run Puppet:
t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp Notice: Compiled catalog for mylaptop in environment production in 1.32 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz
- Run Puppet with the
--graph
option as suggested:t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp --graph Notice: Compiled catalog for mylaptop in environment production in 1.26 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Cycle graph written to /home/tuphill/.puppet/var/state/graphs/cycles.dot. Notice: Finished catalog run in 0.03 seconds
- Check whether the graph files have been created:
t@mylaptop ~/puppet/manifests $ cd ~/.puppet/var/state/graphs t@mylaptop ~/.puppet/var/state/graphs $ ls -l total 16 -rw-rw-r--. 1 thomasthomas 121 Nov 23 23:11 cycles.dot -rw-rw-r--. 1 thomasthomas 2885 Nov 23 23:11 expanded_relationships.dot -rw-rw-r--. 1 thomasthomas 1557 Nov 23 23:11 relationships.dot -rw-rw-r--. 1 thomasthomas 1680 Nov 23 23:11 resources.dot
- Create a graphic using the
dot
command as follows:ubuntu@cookbook:~/puppet$ dot -Tpng -o relationships.png /var/lib/puppet/state/graphs/relationships.dot
- The graphic will look something like the this:
How it works...
When you run puppet agent --graph
(or enable the graph
option in puppet.conf
), Puppet will generate three graphs in the DOT format (a graphics language):
resources.dot
: This shows the hierarchical structure of your classes and resources, but without dependenciesrelationships.dot
: This shows the dependencies between resources as arrows, as shown in the preceding imageexpanded_relationships.dot
: This is a more detailed version of the relationships graph
The dot
tool (part of the graphviz
package) will convert these to an image format such as PNG for viewing.
In the relationships graph, each resource in your manifest is shown as a balloon (known as a vertex), with arrowed lines connecting them to indicate the dependencies. You can see that in our example, the dependencies between File['/etc/ntp.conf']
and Package['ntp']
are bidirectional. When Puppet tries to decide where to begin applying these resources, it can start at File['/etc/ntp.conf']
and look for what depends on File['/etc/ntp.conf']
and end up at Package['ntp']
. When Puppet looks for the dependencies
of Package['ntp']
, it will end up back at File['/etc/ntp.conf']
, forming a circular path. This type of problem is known as a circular dependency problem; Puppet can't decide where to start because the two resources depend on each other.
To fix the circular dependency problem, all you need to do is remove one of the dependency lines and break the circle. The following code fixes the problem:
class trifecta {
package { 'ntp':
ensure => installed,
}
service { 'ntp':
ensure => running,
require => Package['ntp'],
}
file { '/etc/ntp.conf':
source => 'puppet:///modules/trifecta/ntp.conf',
notify => Service['ntp'],
require => Package['ntp'],
}
}
Now when we run puppet apply
or agent
with the --graph
option, the resulting graph does not have any circular paths (cycles):
In this graph it is easy to see that Package[ntp] is the first resource to be applied, then File[/etc/ntp.conf], and finally Service[ntp].
Tip
A graph such as that shown previously is known as a Directed Acyclic Graph (DAG). Reducing the resources to a DAG ensures that Puppet can calculate the shortest path of all the vertices (resources) in linear time. For more information on DAGs, look at http://en.wikipedia.org/wiki/Directed_acyclic_graph.
There's more...
Resource and relationship graphs can be useful even when you don't have a bug to find. If you have a very complex network of classes and resources, for example, studying the resources graph can help you see where to simplify things. Similarly, when dependencies become too complicated to understand from reading the manifest, the graphs can be a useful form of documentation. For instance, a graph will make it readily apparent which resources have the most dependencies and which resources are required by the most other resources. Resources that are required by a large number of other resources will have numerous arrows pointing at them.
See also
- The Using run stages recipe in Chapter 3, Writing Better Manifests
graphviz
package to view the diagram files:
How to do it...
Follow these steps to generate a dependency graph for your manifest:
- Create the directories for a new
trifecta
module:ubuntu@cookbook:~/puppet$ mkdir modules/trifecta ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/manifests ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/files
- Create the file
modules/trifecta/manifests/init.pp
with the following code containing a deliberate circular dependency (can you spot it?):class trifecta { package { 'ntp': ensure => installed, require => File['/etc/ntp.conf'], } service { 'ntp': ensure => running, require => Package['ntp'], } file { '/etc/ntp.conf': source => 'puppet:///modules/trifecta/ntp.conf', notify => Service['ntp'], require => Package['ntp'], } }
- Create a simple
ntp.conf
file:t@mylaptop~/puppet $ cd modules/trifecta/files t@mylaptop~/puppet/modules/trifecta/files $ echo "server 127.0.0.1" >ntp.conf
- Since we'll be working locally on this problem, create a
trifecta.pp
manifest that includes the broken trifecta class:include trifecta
- Run Puppet:
t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp Notice: Compiled catalog for mylaptop in environment production in 1.32 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz
- Run Puppet with the
--graph
option as suggested:t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp --graph Notice: Compiled catalog for mylaptop in environment production in 1.26 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Cycle graph written to /home/tuphill/.puppet/var/state/graphs/cycles.dot. Notice: Finished catalog run in 0.03 seconds
- Check whether the graph files have been created:
t@mylaptop ~/puppet/manifests $ cd ~/.puppet/var/state/graphs t@mylaptop ~/.puppet/var/state/graphs $ ls -l total 16 -rw-rw-r--. 1 thomasthomas 121 Nov 23 23:11 cycles.dot -rw-rw-r--. 1 thomasthomas 2885 Nov 23 23:11 expanded_relationships.dot -rw-rw-r--. 1 thomasthomas 1557 Nov 23 23:11 relationships.dot -rw-rw-r--. 1 thomasthomas 1680 Nov 23 23:11 resources.dot
- Create a graphic using the
dot
command as follows:ubuntu@cookbook:~/puppet$ dot -Tpng -o relationships.png /var/lib/puppet/state/graphs/relationships.dot
- The graphic will look something like the this:
How it works...
When you run puppet agent --graph
(or enable the graph
option in puppet.conf
), Puppet will generate three graphs in the DOT format (a graphics language):
resources.dot
: This shows the hierarchical structure of your classes and resources, but without dependenciesrelationships.dot
: This shows the dependencies between resources as arrows, as shown in the preceding imageexpanded_relationships.dot
: This is a more detailed version of the relationships graph
The dot
tool (part of the graphviz
package) will convert these to an image format such as PNG for viewing.
In the relationships graph, each resource in your manifest is shown as a balloon (known as a vertex), with arrowed lines connecting them to indicate the dependencies. You can see that in our example, the dependencies between File['/etc/ntp.conf']
and Package['ntp']
are bidirectional. When Puppet tries to decide where to begin applying these resources, it can start at File['/etc/ntp.conf']
and look for what depends on File['/etc/ntp.conf']
and end up at Package['ntp']
. When Puppet looks for the dependencies
of Package['ntp']
, it will end up back at File['/etc/ntp.conf']
, forming a circular path. This type of problem is known as a circular dependency problem; Puppet can't decide where to start because the two resources depend on each other.
To fix the circular dependency problem, all you need to do is remove one of the dependency lines and break the circle. The following code fixes the problem:
class trifecta {
package { 'ntp':
ensure => installed,
}
service { 'ntp':
ensure => running,
require => Package['ntp'],
}
file { '/etc/ntp.conf':
source => 'puppet:///modules/trifecta/ntp.conf',
notify => Service['ntp'],
require => Package['ntp'],
}
}
Now when we run puppet apply
or agent
with the --graph
option, the resulting graph does not have any circular paths (cycles):
In this graph it is easy to see that Package[ntp] is the first resource to be applied, then File[/etc/ntp.conf], and finally Service[ntp].
Tip
A graph such as that shown previously is known as a Directed Acyclic Graph (DAG). Reducing the resources to a DAG ensures that Puppet can calculate the shortest path of all the vertices (resources) in linear time. For more information on DAGs, look at http://en.wikipedia.org/wiki/Directed_acyclic_graph.
There's more...
Resource and relationship graphs can be useful even when you don't have a bug to find. If you have a very complex network of classes and resources, for example, studying the resources graph can help you see where to simplify things. Similarly, when dependencies become too complicated to understand from reading the manifest, the graphs can be a useful form of documentation. For instance, a graph will make it readily apparent which resources have the most dependencies and which resources are required by the most other resources. Resources that are required by a large number of other resources will have numerous arrows pointing at them.
See also
- The Using run stages recipe in Chapter 3, Writing Better Manifests
generate a dependency graph for your manifest:
- Create the directories for a new
trifecta
module:ubuntu@cookbook:~/puppet$ mkdir modules/trifecta ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/manifests ubuntu@cookbook:~/puppet$ mkdir modules/trifecta/files
- Create the file
modules/trifecta/manifests/init.pp
with the following code containing a deliberate circular dependency (can you spot it?):class trifecta { package { 'ntp': ensure => installed, require => File['/etc/ntp.conf'], } service { 'ntp': ensure => running, require => Package['ntp'], } file { '/etc/ntp.conf': source => 'puppet:///modules/trifecta/ntp.conf', notify => Service['ntp'], require => Package['ntp'], } }
- Create a simple
ntp.conf
file:t@mylaptop~/puppet $ cd modules/trifecta/files t@mylaptop~/puppet/modules/trifecta/files $ echo "server 127.0.0.1" >ntp.conf
- Since we'll be working locally on this problem, create a
trifecta.pp
manifest that includes the broken trifecta class:include trifecta
- Run Puppet:
t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp Notice: Compiled catalog for mylaptop in environment production in 1.32 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz
- Run Puppet with the
--graph
option as suggested:t@mylaptop ~/puppet/manifests $ puppet apply trifecta.pp --graph Notice: Compiled catalog for mylaptop in environment production in 1.26 seconds Error: Could not apply complete catalog: Found 1 dependency cycle: (File[/etc/ntp.conf] => Package[ntp] => File[/etc/ntp.conf]) Cycle graph written to /home/tuphill/.puppet/var/state/graphs/cycles.dot. Notice: Finished catalog run in 0.03 seconds
- Check whether the graph files have been created:
t@mylaptop ~/puppet/manifests $ cd ~/.puppet/var/state/graphs t@mylaptop ~/.puppet/var/state/graphs $ ls -l total 16 -rw-rw-r--. 1 thomasthomas 121 Nov 23 23:11 cycles.dot -rw-rw-r--. 1 thomasthomas 2885 Nov 23 23:11 expanded_relationships.dot -rw-rw-r--. 1 thomasthomas 1557 Nov 23 23:11 relationships.dot -rw-rw-r--. 1 thomasthomas 1680 Nov 23 23:11 resources.dot
- Create a graphic using the
dot
command as follows:ubuntu@cookbook:~/puppet$ dot -Tpng -o relationships.png /var/lib/puppet/state/graphs/relationships.dot
- The graphic will look something like the this:
How it works...
When you run puppet agent --graph
(or enable the graph
option in puppet.conf
), Puppet will generate three graphs in the DOT format (a graphics language):
resources.dot
: This shows the hierarchical structure of your classes and resources, but without dependenciesrelationships.dot
: This shows the dependencies between resources as arrows, as shown in the preceding imageexpanded_relationships.dot
: This is a more detailed version of the relationships graph
The dot
tool (part of the graphviz
package) will convert these to an image format such as PNG for viewing.
In the relationships graph, each resource in your manifest is shown as a balloon (known as a vertex), with arrowed lines connecting them to indicate the dependencies. You can see that in our example, the dependencies between File['/etc/ntp.conf']
and Package['ntp']
are bidirectional. When Puppet tries to decide where to begin applying these resources, it can start at File['/etc/ntp.conf']
and look for what depends on File['/etc/ntp.conf']
and end up at Package['ntp']
. When Puppet looks for the dependencies
of Package['ntp']
, it will end up back at File['/etc/ntp.conf']
, forming a circular path. This type of problem is known as a circular dependency problem; Puppet can't decide where to start because the two resources depend on each other.
To fix the circular dependency problem, all you need to do is remove one of the dependency lines and break the circle. The following code fixes the problem:
class trifecta {
package { 'ntp':
ensure => installed,
}
service { 'ntp':
ensure => running,
require => Package['ntp'],
}
file { '/etc/ntp.conf':
source => 'puppet:///modules/trifecta/ntp.conf',
notify => Service['ntp'],
require => Package['ntp'],
}
}
Now when we run puppet apply
or agent
with the --graph
option, the resulting graph does not have any circular paths (cycles):
In this graph it is easy to see that Package[ntp] is the first resource to be applied, then File[/etc/ntp.conf], and finally Service[ntp].
Tip
A graph such as that shown previously is known as a Directed Acyclic Graph (DAG). Reducing the resources to a DAG ensures that Puppet can calculate the shortest path of all the vertices (resources) in linear time. For more information on DAGs, look at http://en.wikipedia.org/wiki/Directed_acyclic_graph.
There's more...
Resource and relationship graphs can be useful even when you don't have a bug to find. If you have a very complex network of classes and resources, for example, studying the resources graph can help you see where to simplify things. Similarly, when dependencies become too complicated to understand from reading the manifest, the graphs can be a useful form of documentation. For instance, a graph will make it readily apparent which resources have the most dependencies and which resources are required by the most other resources. Resources that are required by a large number of other resources will have numerous arrows pointing at them.
See also
- The Using run stages recipe in Chapter 3, Writing Better Manifests
run puppet agent --graph
(or enable the graph
option in puppet.conf
), Puppet will generate three graphs in the DOT format (a graphics language):
resources.dot
: This shows the hierarchical structure of your classes and resources, but without dependenciesrelationships.dot
: This shows the dependencies between resources as arrows, as shown in the preceding imageexpanded_relationships.dot
: This is a more detailed version of the relationships graph
The dot
tool (part of the graphviz
package) will convert these to an image format such as PNG for viewing.
In the relationships graph, each resource in your manifest is shown as a balloon (known as a vertex), with arrowed lines connecting them to indicate the dependencies. You can see that in our example, the dependencies between File['/etc/ntp.conf']
and Package['ntp']
are bidirectional. When Puppet tries to decide where to begin applying these resources, it can start at File['/etc/ntp.conf']
and look for what depends on File['/etc/ntp.conf']
and end up at Package['ntp']
. When Puppet looks for the dependencies
of Package['ntp']
, it will end up back at File['/etc/ntp.conf']
, forming a circular path. This type of problem is known as a circular dependency problem; Puppet can't decide where to start because the two resources depend on each other.
To fix the circular dependency problem, all you need to do is remove one of the dependency lines and break the circle. The following code fixes the problem:
class trifecta {
package { 'ntp':
ensure => installed,
}
service { 'ntp':
ensure => running,
require => Package['ntp'],
}
file { '/etc/ntp.conf':
source => 'puppet:///modules/trifecta/ntp.conf',
notify => Service['ntp'],
require => Package['ntp'],
}
}
Now when we run puppet apply
or agent
with the --graph
option, the resulting graph does not have any circular paths (cycles):
In this graph it is easy to see that Package[ntp] is the first resource to be applied, then File[/etc/ntp.conf], and finally Service[ntp].
Tip
A graph such as that shown previously is known as a Directed Acyclic Graph (DAG). Reducing the resources to a DAG ensures that Puppet can calculate the shortest path of all the vertices (resources) in linear time. For more information on DAGs, look at http://en.wikipedia.org/wiki/Directed_acyclic_graph.
There's more...
Resource and relationship graphs can be useful even when you don't have a bug to find. If you have a very complex network of classes and resources, for example, studying the resources graph can help you see where to simplify things. Similarly, when dependencies become too complicated to understand from reading the manifest, the graphs can be a useful form of documentation. For instance, a graph will make it readily apparent which resources have the most dependencies and which resources are required by the most other resources. Resources that are required by a large number of other resources will have numerous arrows pointing at them.
See also
- The Using run stages recipe in Chapter 3, Writing Better Manifests
and relationship graphs can be useful even when you don't have a bug to find. If you have a very complex network of classes and resources, for example, studying the resources graph can help you see where to simplify things. Similarly, when dependencies become too complicated to understand from reading the manifest, the graphs can be a useful form of documentation. For instance, a graph will make it readily apparent which resources have the most dependencies and which resources are required by the most other resources. Resources that are required by a large number of other resources will have numerous arrows pointing at them.
See also
- The Using run stages recipe in Chapter 3, Writing Better Manifests
- Chapter 3, Writing Better Manifests
Understanding Puppet errors
Puppet's error messages can sometimes be a little confusing. Updated and increasingly helpful error messages are one reason to upgrade your Puppet installation if you are running any version prior to Version 3.
Here are some of the most common errors you might encounter, and what to do about them.
How to do it...
Often the first step is simply to search the Web for the error message text and see what explanations you can find for the error, along with any helpful advice about fixing it. Here are some of the most common puzzling errors, with possible explanations:
Could not retrieve file metadata for XXX: getaddrinfo: Name or service not known
Where XXX
is a file resource, you may have accidentally typed puppet://modules...
in a file source instead of puppet:///modules...
(note the triple slash):
Could not evaluate: Could not retrieve information from environment production source(s) XXX
The source file may not be present or may not be in the right location in the Puppet repo:
Error: Could not set 'file' on ensure: No such file or directory XXX
The file path may specify a parent directory (or directories) that doesn't exist. You can use separate file resources in Puppet to create these:
change from absent to file failed: Could not set 'file on ensure: No such file or directory
This is often caused by Puppet trying to write a file to a directory that doesn't exist. Check that the directory either exists already or is defined in Puppet, and that the file resource requires the directory (so that the directory is always created first):
undefined method 'closed?' for nil:NilClass
This unhelpful error message is roughly translated as something went wrong. It tends to be a catch-all error caused by many different problems, but you may be able to determine what is wrong from the name of the resource, the class, or the module. One trick is to add the --debug
switch, to get more useful information:
[root@cookbook ~]# puppet agent -t --debug
If you check your Git history to see what was touched in the most recent change, this may be another way to identify what's upsetting Puppet:
Could not parse for environment --- "--- production": Syntax error at end of file at line 1
This can be caused by mistyping command line options, for example, if you type puppet -verbose
instead of puppet --verbose
. This kind of error can be hard to see:
Duplicate definition: X is already defined in [file] at line Y; cannot redefine at [file] line Y
This one has caused me a bit of puzzlement in the past. Puppet's complaining about a duplicate definition, and normally if you have two resources with the same name, Puppet will helpfully tell you where they are both defined. But in this case, it's indicating the same file and line number for both. How can one resource be a duplicate of itself?
The answer is, if it's a defined type (a resource created with the define
keyword). If you create two instances of a defined type you'll also have two instances of all the resources contained within the definition, and they need to have distinct names. For example:
define check_process() {
exec { 'is-process-running?':
command => "/bin/ps ax |/bin/grep ${name} >/tmp/pslist.${name}.txt",
}
}
check_process { 'exim': }
check_process { 'nagios': }
When we run Puppet, the same error is printed twice:
t@mylaptop ~$ puppet apply duplicate.pp
Error: Duplicate declaration: Exec[is-process-running?] is already declared in file duplicate.pp:4; cannot redeclare at duplicate.pp:4 on node cookbook.example.com
Error: Duplicate declaration: Exec[is-process-running?] is already declared in file duplicate.pp:4; cannot redeclare at duplicate.pp:4 on node cookbook.example.com
Because the exec
resource is named is-process-running?
, if you try to create more than one instance of the definition, Puppet will refuse because the result would be two exec
resources with the same name. The solution is to include the name of the instance (or some other unique value) in the title of each resource:
exec { "is-process-${name}-running?":
command => "/bin/ps ax |/bin/grep ${name} >/tmp/pslist.${name}.txt",
}
Every resource must have a unique name, and a good way to ensure this with a definition is to interpolate the ${name}
variable in its title. Note that we switched from using single to double quotes in the resource title:
"is-process-${name}-running?"
The double quotes are required when you want Puppet to interpolate the value of a variable into a string.
See also
- The Generating reports recipe in this chapter
- The Noop: the don't change anything option recipe in this chapter
- The Logging debug messages recipe in this chapter
XXX
is a file resource, you may have accidentally typed puppet://modules...
in a file source instead of puppet:///modules...
(note the triple slash):
--debug
switch, to get more useful information:
puppet -verbose
instead of puppet --verbose
. This kind of error can be hard to see:
caused me a bit of puzzlement in the past. Puppet's complaining about a duplicate definition, and normally if you have two resources with the same name, Puppet will helpfully tell you where they are both defined. But in this case, it's indicating the same file and line number for both. How can one resource be a duplicate of itself?
The answer is, if it's a defined type (a resource created with the define
keyword). If you create two instances of a defined type you'll also have two instances of all the resources contained within the definition, and they need to have distinct names. For example:
define check_process() {
exec { 'is-process-running?':
command => "/bin/ps ax |/bin/grep ${name} >/tmp/pslist.${name}.txt",
}
}
check_process { 'exim': }
check_process { 'nagios': }
When we run Puppet, the same error is printed twice:
t@mylaptop ~$ puppet apply duplicate.pp
Error: Duplicate declaration: Exec[is-process-running?] is already declared in file duplicate.pp:4; cannot redeclare at duplicate.pp:4 on node cookbook.example.com
Error: Duplicate declaration: Exec[is-process-running?] is already declared in file duplicate.pp:4; cannot redeclare at duplicate.pp:4 on node cookbook.example.com
Because the exec
resource is named is-process-running?
, if you try to create more than one instance of the definition, Puppet will refuse because the result would be two exec
resources with the same name. The solution is to include the name of the instance (or some other unique value) in the title of each resource:
exec { "is-process-${name}-running?":
command => "/bin/ps ax |/bin/grep ${name} >/tmp/pslist.${name}.txt",
}
Every resource must have a unique name, and a good way to ensure this with a definition is to interpolate the ${name}
variable in its title. Note that we switched from using single to double quotes in the resource title:
"is-process-${name}-running?"
The double quotes are required when you want Puppet to interpolate the value of a variable into a string.
See also
- The Generating reports recipe in this chapter
- The Noop: the don't change anything option recipe in this chapter
- The Logging debug messages recipe in this chapter
Inspecting configuration settings
You probably know that Puppet's configuration settings are stored in puppet.conf
, but there are many parameters, and those that aren't listed in puppet.conf
will take a default value. How can you see the value of any configuration parameter, regardless of whether or not it's explicitly set in puppet.conf
? The answer is to use the puppet config print
command.
How to do it...
Run the following command. This will produce a lot of output (it may be helpful to pipe it through less
if you'd like to browse the available configuration settings):
[root@cookbook ~]# puppet config print |head -25
report_serialization_format = pson
hostcsr = /var/lib/puppet/ssl/csr_cookbook.example.com.pem
filetimeout = 15
masterhttplog = /var/log/puppet/masterhttp.log
pluginsignore = .svn CVS .git
ldapclassattrs = puppetclass
certdir = /var/lib/puppet/ssl/certs
ignoreschedules = false
disable_per_environment_manifest = false
archive_files = false
hiera_config = /etc/puppet/hiera.yaml
req_bits = 4096
clientyamldir = /var/lib/puppet/client_yaml
evaltrace = false
module_working_dir = /var/lib/puppet/puppet-module
tags =
cacrl = /var/lib/puppet/ssl/ca/ca_crl.pem
manifest = /etc/puppet/manifests/site.pp
inventory_port = 8140
ignoreimport = false
dbuser = puppet
postrun_command =
document_all = false
splaylimit = 1800
certificate_expire_warning = 5184000
How it works...
Running puppet config print
will output every configuration parameter and its current value (and there are lots of them).
To see the value for a specific parameter, add it as an argument to puppet config print
command:
[root@cookbook ~]# puppet config print modulepath
/etc/puppet/modules:/usr/share/puppet/modules
See also
- The Generating reports recipe in this chapter
less
if you'd like to browse the available configuration settings):
How it works...
Running puppet config print
will output every configuration parameter and its current value (and there are lots of them).
To see the value for a specific parameter, add it as an argument to puppet config print
command:
[root@cookbook ~]# puppet config print modulepath
/etc/puppet/modules:/usr/share/puppet/modules
See also
- The Generating reports recipe in this chapter
puppet config print
will
output every configuration parameter and its current value (and there are lots of them).
To see the value for a specific parameter, add it as an argument to puppet config print
command:
[root@cookbook ~]# puppet config print modulepath
/etc/puppet/modules:/usr/share/puppet/modules
See also
- The Generating reports recipe in this chapter