Frequently Asked Questions
- General
- What is Puppet?
- Who maintains this FAQ and where can I find an updated version?
- What license is Puppet released under?
- Why does Puppet exist?
- Why does Puppet have its own language?
- Why is Puppet written in Ruby?
- How does Puppet compare to cfengine?
- How does Puppet compare to available commercial products?
- Who would find Puppet useful?
- Can Puppet manage workstations?
- Does Puppet run on Windows?
- What size organizations should use Puppet?
- My servers are all unique; can Puppet still help?
- Where can I get Puppet?
- When is the Next Release?
- I have found a security issue in Puppet. Who do I tell?
- Recent Notifications
- Who is Puppet Labs (formerly Reductive Labs)?
- How do I contribute?
- Installation
- How Do I Install Puppet?
- What Is The Minimum Version of Ruby?
- Upgrading
- Should I upgrade the client or server first?
- How should I upgrade Puppet and Facter?
- How do I know what's changed when I upgrade?
- Configuration
- What is a Manifest?
- How Do I Write Manifests?
- What characters are permitted in a class name?
- How Do I Run Manifests?
- How do I document my manifests?
- How do I manage passwords on Red Hat Enterprise Linux & Fedora Core?
- How do I use Puppet's graphing support?
- How do all of these variables, like \$operatingsystem, get set?
- Are there variables available other than those provided by Facter?
- Can I access environmental variables with Facter?
- Why shouldn't I use autosign for all my clients?
- Techniques
- How Can I Manage Whole Directories of Files Without Explicitly Listing the Files?
- I Want To Manage A Directory and Purge Its Contents
- How Do I Run a Command Whenever A File Changes?
- How Can I Ensure a Group Exists Before Creating a User?
- How Can I Require Multiple Resources Simultaneously?
- Can I use complex comparisons in if statements and variables?
- Can I output Facter facts in YAML?
- Can I check the syntax of my templates?
- Troubleshooting
- Why hasn't my new node configuration been noticed?
- Why don't my certificates show as waiting to be signed on my server when I do a "puppetca --list"?
- I keep getting "certificates were not trusted". What's wrong?
- I'm getting IPv6 errors; what's wrong?
- I'm getting tlsv1 alert unknown ca errors; what's wrong?
- Why does Puppet keep trying to start a running service?
- I'm using the Nagios types but the Puppet run on the server running Nagios is starting to take ages
- Why is my external node configuration failing ? I get no errors by running the script by hand.
- Puppet Syntax Errors
- Syntax error at '}'; expected '}' at manifest.pp:nnn
- Syntax error at ':'; expected ']' at manifest.pp:nnn
- Syntax error at '.'; expected '}' at manifest.pp:nnn
- Could not match '\_define\_name' at manifest.pp:nnn on node nodename
- Duplicate definition: Classname::Define\_name[system] is already defined in file manifest.pp at line nnn; cannot redefine at manifest.pp:nnn on node nodename
- Syntax error at '=>'; expected ')'
- err: Exported resource Blah[$some\_title] cannot override local resource on node $nodename
- Common Misconceptions
- Node Inheritance and Variable Scope
- Class Inheritance and Variable Scope
- Custom Type & Provider development
- err: Could not retrieve catalog: Invalid parameter 'foo' for type 'bar'
General
What is Puppet?
Puppet is an open-source next-generation server automation tool. It is composed of a declarative language for expressing system configuration, a client and server for distributing it, and a library for realizing the configuration.
The primary design goal of Puppet is that it have an expressive enough language backed by a powerful enough library that you can write your own server automation applications in just a few lines of code. With Puppet, you can express the configuration of your entire network in one program capable of realizing the configuration. The fact that Puppet has open source combined with how easily it can be extended means that you can add whatever functionality you think is missing and then contribute it back to the main project if you desire.
For more about the capabilities of Puppet, take a look at Documentation Start.
Who maintains this FAQ and where can I find an updated version?
This FAQ is maintained by wiki at Puppet Labs. Please send comments, additions, omissions, and errors to:
faq at puppetlabs dot com
What license is Puppet released under?
Puppet is open source and is released under the GNU Public License.
Why does Puppet exist?
Luke Kanies, who founded Puppet Labs, has been doing server automation for years, and Puppet is the result of his frustration with existing tools. After significant effort spent trying to enhance cfengine, plus a stint at a commercial server automation vendor, Luke concluded that the only way to get a great automation tool was to develop one.
Puppet is actually the result of years of design and prototyping (called Blink during its prototype phases), but only in 2005 was a commercial company (Puppet Labs) built to be fully dedicated to its creation. If Puppet is not the most powerful and most flexible server automation platform available, then its goals are not being met.
Why does Puppet have its own language?
This actually is a frequently asked question, and people most often ask why I did not choose to use something like XML or YAML as the configuration format; otherwise people ask why I didn’t just choose to just use Ruby as the input language (although you can use Ruby as an input language in version 2.6.0 and later).
The input format for Puppet is not XML or YAML because these are data formats developed to be easy for computers to handle. They do not do conditionals (although, yes, they support data structures that could be considered conditionals), but mostly, they’re just horrible human interfaces. While some people are comfortable reading and writing them, there is a reason why we use web browsers instead of just reading the HTML directly. Also, using XML or YAML would limit the ability to make sure the interface is declarative — one process might treat an XML configuration differently from another.
As to just using Ruby as the input format we do provide that functionality in version 2.6.0. Ruby provides a quite a lot of functionality, you should be cautious using it. We believe systems administrators should be able to model their datacenters in a higher level system, and for those that need the power of Ruby, writing custom functions, types, and providers is possible.
Why is Puppet written in Ruby?
From Luke Kanies, Puppet’s author: I was a sysadmin by trade and had mostly developed in perl, but when I tried to write the prototype I had in mind, I couldn’t get the class relationships I wanted in perl. I tried Python, because this was around 2003 and Python was the next new thing and everyone was saying how great it is, but I just can’t seem to write in Python at all. A friend had said he’d heard Ruby was cool, so I gave it a try, and in four hours I went from never having seen a line of it to having a working prototype. I haven’t looked back since then, and haven’t regretted the choice.
How does Puppet compare to cfengine?
Puppet could be said to be the next-generation cfengine. The overall design is heavily influenced by cfengine, but the language is more powerful than cfengine’s and the library is more flexible. In addition, Puppet’s client and server use standard protocols like RESTful HTTP and are easy to enhance with new functionality, so they are well-positioned to become the platform for the network applications of the future, while cfengine’s client and server rely entirely on cfengine-specific protocols and are quite difficult to enhance.
How does Puppet compare to available commercial products?
The primary commercial vendors are BladeLogic and OpsWare. While they both have useful product lines, Puppet surpasses them by re-framing the entire server automation problem — while the commercial vendors are writing GUI applications for you, Puppet Labs is providing a development platform with all the features of a great language, like library development, code sharing, and the ability to version control your configurations.
Trying to express a complex network configuration entirely through a GUI is an exercise in frustration that no one should suffer, but expressing the abstraction necessary to share those GUI configurations goes beyond frustrating.
Of course, another great difference between Puppet and the commercial products is that Puppet is open sourced under the GNU Public License. You can download the product, try it out, peruse the source, and make whatever modifications you want. You have to have more than 100 servers just to get a demo from the commercial vendors, but Puppet is available for testing by any company that needs to reduce its server administration costs.
Who would find Puppet useful?
Any organization that would like to reduce the cost of maintaining its computers could benefit from using Puppet. However, because the return on investment is linked to multiple factors, like current administrative overhead, diversity among existing computers, and cost of downtime, it can be difficult for organizations to determine whether they should invest in any configuration management tools, much less Puppet. Puppet Labs can always be contacted directly at info at puppetlabs.com to help answer this question.
Generally, however, an organization should be using server automation if any of the following are true:
- It has high server administration costs
- It pays a high price for downtime, either because of contracts or opportunity cost
- It has many servers that are essentially either identical or nearly identical
- Flexibility and agility in server configuration are essential
Can Puppet manage workstations?
Yes, Puppet can manage any type of machine. We have found that most organizations are more concerned with server management than workstation management, and frankly, the term ‘server’ is slightly more aesthetically appealing than ‘computer’, but Puppet would be ideal for organizations with a large number of workstations.
Does Puppet run on Windows?
We have basic Windows support available in the 2.6.0 release.
What size organizations should use Puppet?
There is no minimum or maximum organization size that can benefit from Puppet, but there are sizes that are more likely to benefit. Organizations with fewer than 10-20 servers are unlikely to consider maintaining those servers to be a real problem, and thus they can avoid investment in tools even though those tools could likely provide savings.
There is no real upper limit to who could benefit from using Puppet. Obviously as the server count increases the investment must increase somewhat, but with Puppet that increase is not linear.
My servers are all unique; can Puppet still help?
All servers are at least somewhat unique — with different host names and different IP addresses — but very few servers are entirely unique, since nearly every one runs a relatively standard operating system. Servers are also often very similar to other servers within a single organization — all Solaris servers might have similar security settings, or all web servers might have roughly equivalent configurations — even if they’re very different from servers in other organizations. Finally, servers are often needlessly unique, in that they have been built and managed manually with no attempt at retaining appropriate consistency.
Puppet can help both on the side of consistency and uniqueness. Puppet can be used to express the consistency that should exist, even if that consistency spans arbitrary sets of servers based on any type of data like operating system, data centre, or physical location. Puppet can also be used to handle uniqueness, either by allowing special provision of what makes a given host unique or through specifying exceptions to otherwise standard classes.
Where can I get Puppet?
You can always find the latest release in the download directory. Currently, puppet is being tracked on Freshmeat, and RubyForge.
When is the Next Release?
There are regular feature and release updates on the Mailing List, and you can always find the latest release in the download directory.
I have found a security issue in Puppet. Who do I tell?
Puppet Labs and the Puppet project take security very seriously. We handle all security problems brought to our attention and ensure that they are corrected within a reasonable time frame.
If you have identified an issue then please send an email to the Security mailbox <security@puppetlabs.net> with the details.
Recent Notifications
Experience has shown that “security through obscurity” does not work. Public disclosure allows for more rapid and better solutions to security problems. In that vein, this page addresses Puppet’s status with respect to various known security holes, which could potentially affect Puppet.
- CVE-2009-3564 – Resolved in 0.25.2
- CVE-2010-0156 – Resolved in 0.25.2
Who is Puppet Labs (formerly Reductive Labs)?
Puppet Labs is a small, private company focused on re-framing the server automation problem. Our primary focus is Puppet, but Puppet Labs also provides automation consulting, training, and custom development.
Puppet Labs was formerly known as Reductive Labs.
For more information email info at puppetlabs.com.
The Projects page lists our active projects.
How do I contribute?
First, join one or both of the Mailing Lists. There is currently a development list, and a user discussion list as well. You can also join the IRC channel #puppet on irc.freenode.net, where Puppet’s developers will be hanging out most days (and nights).
If you are interested in helping with Puppet’s development you can read about how it is developed and how to submit patches and fixes on the Development Lifecycle wiki page.
The most valuable contribution you can make, though, is to use Puppet and submit your feedback, either directly on IRC or through the mailing list, or by reporting to the bug database. We’re always looking for great ideas to incorporate into Puppet.
Installation
How Do I Install Puppet?
The Installation Guide documents the fastest way to start using Puppet.
What Is The Minimum Version of Ruby?
Puppet is supported on all versions of Ruby from 1.8.2 on up. It will sometimes work on 1.8.1, but it’s not supported on that release.
Upgrading
Should I upgrade the client or server first?
When upgrading to a new version of Puppet, always upgrade the server first. Old clients can point at a new server but you may have problems when pointing a new client at an old server.
How should I upgrade Puppet and Facter?
The best way to install and to upgrade Puppet and Facter is via your operating system’s package management system. This is easier than installing them from source. If you do install them from source make sure you remove old versions including all application and library files (excepting configuration in /etc/puppet obviously) entirely before upgrading.
How do I know what’s changed when I upgrade?
The best way to find out what’s changed in Puppet is to read the Release Notes. They will tell you about new features, functions, deprecations and other changes to Puppet.
Configuration
What is a Manifest?
Because the word script implies a procedural one-step-after-another program, the word does not apply well to Puppet programs. Thus, we use the word manifest to describe declarative Puppet programs. Speaking of applying, Puppet applies a manifest to a server or a network, rather than executing it.
How Do I Write Manifests?
The best way is to download Puppet and just start writing. There are multiple sets of examples including publicly available Puppet Modules and the Language Tutorial will obviously be useful.
What characters are permitted in a class name?
Alphanumeric and hyphen ‘–’, nothing else. If you intend on using qualified variables, don’t use hyphen.
How Do I Run Manifests?
Once you have Puppet installed according the the Installation Guide, just run the puppet executable against your example:
puppet -v example.pp
How do I document my manifests?
Using some simple documentation syntax (which you can see on the Puppet Manifest Documentation Wiki page) and the puppetdoc command you can generate automated documentation in RDoc or HTML for your manifests and modules.
How do I manage passwords on Red Hat Enterprise Linux & Fedora Core?
As described in the TypeReference you need the Shadow Password Library, this is provided by the ruby-shadow package. The ruby-shadow library is available natively for fc6 (and higher) and should build on the RHEL and CentOS variants that match.
How do I use Puppet’s graphing support?
Puppet has graphing support capable of creating graph files of your Puppet client configurations. The graphs are created by and on the client, so you must enable the graph option. This will create files in dot format in a directory on the client specified by the graphdir configuration option.
These files are text files and need to be interpreted by another application to get turned into images. The easiest way to do this is to use OmniGraffle, since it automatically converts them to attractive graphs, but it only runs on OS X. You can also install graphviz, which comes with the dot application, which you can use to turn the text files into images:
dot -Tpng /var/puppet/state/graphs/resources.dot -o /tmp/configuration.png
How do all of these variables, like \$operatingsystem, get set?
The variables are all set by Facter. You can get a full listing of the available variables and their values by running facter by itself in a shell.:
\# facter
Are there variables available other than those provided by Facter?
Puppet also provides a few in-built variables you can use in your manifests.
The first is provided by the Puppet client and returns the current environment, appropriately it is called $environment.
Also available are the $servername, $serverip and $serverversion variables. These contain the fully-qualified domain, IP address, and Puppet version of the server respectively.
Can I access environmental variables with Facter?
Not directly no but Facter has a special types of facts that can be set from environment variables. Any environment variable with a prefix of FACTER will be taken by Facter and converted into a fact, for example:
$ FACTER_FOO="bar"
$ export FACTER_FOO
$ facter | grep 'foo'
foo => bar
The value of the FACTER_FOO environmental variable would now be
available in your Puppet manifests as $foo with a value of ‘bar’.
Why shouldn’t I use autosign for all my clients?
It is very tempting to enable autosign for all nodes, as it cuts down on the manual steps required to bootstrap a new node (or indeed to move it to a new puppetmaster).
Typically this would be done with a *.mydomain.com or even * in the autosign.conf file.
This however can be very dangerous as it can enable a node to masquerade as another node, and get the configuration intended for that node. The reason for this is that the node chooses the certificate common name (‘CN’ – usually its fqdn, but this is fully configurable), and the puppetmaster then uses this CN to look up the node definition to serve. The certificate itself is stored, so two nodes could not connect with the same CN (eg alice.mydomain.com), but this is not the problem.
The problem lies in the fact that the puppetmaster does not make a 1-1 mapping between a node and the first certificate it saw for it, and hence multiple certificates can map to the same node, for example:
- alice.mydomain.com connects, gets node alice { } definition.
- bob.mydomain.com connects with CN alice.bob.mydomain.com, and also matches node alice { } definition.
Without autosigning, it would be apparent that bob was trying to get alice’s configuration – as the puppetca process lists the full fqdn/CN presented. With autosign turned on, bob silently retrieves alice’s configuration.
Depending on your environment, this may not present a significant risk. It essentially boils down to the question ‘Do I trust everything that can connect to my Puppetmaster?’.
If you do still choose to have a permanent, or semi-permanent, permissive autosign.conf, please consider doing the following:
- Firewall your puppetmaster – restrict port tcp/8140 to only networks that you trust.
- Create puppetmasters for each ‘trust zone’, and only include the trusted nodes in that Puppet masters manifest.
- Never use a full wildcard such as *
Techniques
How Can I Manage Whole Directories of Files Without Explicitly Listing the Files?
The file type has a parameter recurse which can be used to synchronize the contents of a target directory recursively with a chosen source. In the example below, the entire /etc/httpd/conf.d directory is synchronized recursively with the copy on the server:
file { "/etc/httpd/conf.d":
source => "puppet://server/vol/mnt1/adm/httpd/conf.d",
recurse => "true"
}
I Want To Manage A Directory and Purge Its Contents
Many people try to do something like this:
file { "/etc/nagios/conf.d":
owner => nagios,
group => nagios,
purge => true,
recurse => true,
force => true,
}
NOTE: It appears the above resource now works in 0.25.5, so there’s no need for the hack below – which does not work any more :)
It seems what most people expect to happen here is create the named directory, set the owner and group, then purge any files or directories that are not managed by puppet underneath that. But this is not the behaviour puppet will display. In fact the purge will silently fail.
The workaround is to define a source for the directory that doesn’t exist.
file { "/etc/nagios/conf.d":
owner => nagios,
group => nagios,
purge => true,
recurse => true,
force => true,
source => "puppet:///nagios/emtpy",
}
The fileserver context (here ‘nagios’) must exist and be created by the fileserver and an empty directory must also exist, and puppet will purge the files as expected.
How Do I Run a Command Whenever A File Changes?
The answer is to use an exec resource with refreshonly set to true, such as in this case of telling bind to reload its configuration when it changes:
file { "/etc/bind": source => "/dist/apps/bind" }
exec { "/usr/bin/ndc reload":
subscribe => File["/etc/bind"],
refreshonly => true
}
The exec has to subscribe to the file so it gets notified of changes.
How Can I Ensure a Group Exists Before Creating a User?
In the example given below, we’d like to create a user called tim who we want to put in the fearme group. By using the require parameter, we can create a dependency between the user tim and the group fearme. The result is that user tim will not be created until puppet is certain that the fearme group exists.
group { "fearme":
ensure => present,
gid => 1000
}
user { "tim":
ensure => present,
gid => "fearme",
groups => ["adm", "staff", "root"],
membership => minimum,
shell => "/bin/bash",
require => Group["fearme"]
}
Note that Puppet will set this relationship up for you automatically, so you should not normally need to do this.
How Can I Require Multiple Resources Simultaneously?
In the example given below, we’re again adding the user tim (just as we did earlier in this document), but in addition to requiring tim’s primary group, fearme, we’re also requiring another group, fearmenot. Any reasonable number of resources can be required in this way.
user { "tim":
ensure => present,
gid => "fearme",
groups => ["adm", "staff", "root", "fearmenot"],
membership => minimum,
shell => "/bin/bash",
require => [ Group["fearme"],
Group["fearmenot"]
]
}
Can I use complex comparisons in if statements and variables?
In Puppet version 0.24.6 onwards you can use complex expressions in if statements and variable assignments. You can see examples of how to do this in the Language Tutorial.
In versions prior to 0.24.6 Puppet does not support complex conditionals: if can only test for the existence of a variable, and case can only switch on a defined string.
However, a workaround is possible by using the generate() function to call out to Ruby or Perl to perform the comparison, e.g:
if generate('/usr/bin/env', 'ruby', '-e', 'puts :true if eval ARGV[0]', "'$operatingsystem' =~ /redhat/") {
# do stuff
}
The Perl equivalent is:
if generate('/usr/bin/env', 'perl', '-e', 'print("true") if (eval shift)', "'$operatingsystem' =~ /redhat/") {
# do stuff
}
Note that the generate() function is executed on the Puppet master at manifest compilation, so cannot be used client-side. Also note the quoting around the final option – this is to ensure that $operatingsystem variable is interpolated by the parser and passed to the Ruby or Perl interpreter as a string.
Can I output Facter facts in YAML?
Facter supports output of facts in YAML as well as to standard out. You need to run:
\# facter --yaml
To get this output, which you can redirect to a file for further processing.
Can I check the syntax of my templates?
ERB files are easy to syntax check. For a file mytemplate.erb, run:
\$ erb -x -T '-' mytemplate.erb | ruby -c
The trim option specified corresponds to what Puppet uses.
Troubleshooting
Why hasn’t my new node configuration been noticed?
If you’re using separate node definition files and import them into site.pp with an import *.node (for example) you’ll find that new files added won’t get noticed until you restart puppetmasterd. This is due to the fact globs aren’t evaluated on each run, but only when the ‘parent’ file is re-read.
To make sure your new file is actually read, simply ‘touch’ the site.pp (or importing file) and the glob will be re-evaluated.
Why don’t my certificates show as waiting to be signed on my server when I do a “puppetca —list”?
puppetca must be run as root. If you are not root then rerun the command with sudo:
\$ sudo puppetca --list
I keep getting “certificates were not trusted”. What’s wrong?
Firstly, if you’re re-installing a machine, you probably haven’t cleared the previous certificate for that machine. To correct the problem:
- Run “sudo puppetca —clean <fqdn>” on the Puppetmaster to clear the certificates.
Remove the entire SSL directory of the client machine:
$ sudo rm -r etc/puppet/ssl rm -r /var/lib/puppet/ssl
Assuming that you’re not re-installing, by far the most common cause of SSL problems is that the clock on the client machine is set incorrectly, which confuses SSL because the “validFrom” date in the certificate is in the future.
You can figure the problem out by manually verifying the certificate with openssl:
$ sudo openssl verify -CAfile /etc/puppet/ssl/certs/ca.pem /etc/puppet/ssl/certs/myhostname.domain.com.pem
This can also happen if you’ve followed the Using Mongrel recipe to alleviate file download problems. If your set-up is such that the host name differs from the name in the Puppet server certificate, or there is any other SSL certificate negotiation problem, the SSL handshake between client and server will fail. In this case, either alleviate the SSL handshake problems (debug using cURL), or revert to the original Webrick installation.
I’m getting IPv6 errors; what’s wrong?
This can apparently happen if Ruby is not compiled with IPv6 support; see the mail thread for more details. The only known solution is to make sure you’re running a version of Ruby compiled with IPv6 support.
I’m getting tlsv1 alert unknown ca errors; what’s wrong?
This problem is caused by puppetmasterd not being able to read its ca certificate. This problem might occur up to 0.18.4 but has been fixed in 0.19.0. You can probably fix it for versions before 0.19.0 by changing the group ownership of the /etc/puppet/ssl directory to the puppet group, but puppetd may change the group back. Having puppetmasterd start as the root user should fix the problem permanently until you can upgrade.
Why does Puppet keep trying to start a running service?
The ideal way to check for a service is to use the hasstatus parameter, which calls the init script with the status parameter. This should report back to Puppet whether the service is running or stopped.
In some broken scripts, however, the status output will be correct (“Ok” or “not running”), but the exit code of the script will be incorrect. Most commonly, the script will always blindly return 0, no matter what the actual service state is. Puppet only uses the exit code, so interprets this as “the service is stopped”.
There are two workarounds, and one fix. If you must deal with the scripts broken behaviour as is, you can modify your resource to either use the pattern parameter to look for a particular process name, or the status parameter to use a custom script to check for the service status.
The fix is to rewrite the init script to use the proper exit codes. When rewriting them, or submitting bug reports to vendors or upstream, be sure to reference the LSB Init Script Actions standard. This should carry more weight by pointing out an official, published standard they’re failing to meet, rather than trying to explain how their bug is causing problems in Puppet.
I’m using the Nagios types but the Puppet run on the server running Nagios is starting to take ages
Note: This has heavily been improved with 0.25 and it is no longer a problem. The proposed workaround should be considered only on systems running puppet < 0.25
If you are exporting Nagios objects, they will need to be collected on your Nagios server to be added to the nagios service configuration file.
Let’s say you are exporting some hundreds of nagios_service objects, the corresponding nagios_service.cfg file will be quite large. On every puppet run however, for each and every nagios_service defined, puppet will have to seek through that file to see if anything has changed. This is incredibly time consuming.
You’ll have better results using the “target” option for the nagios_service type, e.g.
nagios_service { "check_ssh_$fqdn":
ensure => present,
check_command => "check_ssh",
use => "generic-service",
host_name => $fqdn,
service_description => "SSH",
target => "/etc/nagios/nagios_service.d/check_ssh_$fqdn"
}
This will dramatically improve your puppet run performance, as puppet only has to look in the directory for the file it needs and seek through a file with only one service definition in it.
Why is my external node configuration failing ? I get no errors by running the script by hand.
Most of the time, if you get the following error when running you client
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
it is because of some invalid YAML output from your external node script. Check Yaml.org if you have doubts about validity.
Puppet Syntax Errors
Puppet generates syntax errors when manifests are incorrectly written. Sometimes these errors can be a little cryptic. Below is a list of common errors and their explanations that should help you trouble-shoot your manifests.
Syntax error at ‘}’; expected ‘}’ at manifest.pp:nnn
This error can occur when:
service { "fred" }
This contrived example demonstrates one way to get the very confusing error of Puppet’s parser expecting what it found. In this example, the colon ( : ) is missing after the service title. A variant looks like:
service { "fred"
ensure => running
}
and the error would be Syntax error at ‘ensure’; expected ‘}’ .
You can also get the same error if you forget a comma. For instance, in this example the comma is missing at the end of line 3:
service {
"myservice":
provider => "runit"
path => "/path/to/daemons"
}
Syntax error at ‘:’; expected ‘]’ at manifest.pp:nnn
This error can occur when:
classname::define_name {
"jdbc/automation":
cpoolid => "automationPool",
require => [ Classname::other_define_name["automationPool"] ],
}
The problem here is that Puppet requires that object references in the require lines to begin with a capital letter. However, since this is a reference to a class and a define, the define also needs to have a capital letter, so Classname::Other_define_name would be the correct syntax.
Syntax error at ‘.’; expected ‘}’ at manifest.pp:nnn
This error happens when you use unquoted comparators with dots in them, for example:
class autofs {
case $kernelversion {
2.6.9: { $autofs_packages = ["autofs", "autofs5"] }
default: { $autofs_packages = ["autofs"] }
}
}
That 2.6.9 needs to have double quotes around it, like so:
class autofs {
case $kernelversion {
"2.6.9": { $autofs_packages = ["autofs", "autofs5"] }
default: { $autofs_packages = ["autofs"] }
}
}
Could not match ‘_define_name’ at manifest.pp:nnn on node nodename
This error can occur using a manifest like:
case $ensure {
"present": {
_define_name {
"$title":
user => $user,
}
}
}
This one is simple – you cannot begin a function name (define name) with an underscore.
Duplicate definition: Classname::Define_name[system] is already defined in file manifest.pp at line nnn; cannot redefine at manifest.pp:nnn on node nodename
This error can occur when using a manifest like:
Classname::define_name {
"system":
properties => "Name=system";
.....
"system":
properties => "Name=system";
}
The most confusing part of this error is that the line numbers are usually the same – this is the case when using the block format that Puppet supports for a resource definition. In this contrived example, the system entry has been defined twice, so one of them needs removing.
Syntax error at ‘=>’; expected ‘)’
This error can occur when you use a manifest like:
define foo($param => 'value') { ... }
Default values for parameters are assigned, not defined, therefore a ‘=’, not a ‘=>’ operator is needed.
err: Exported resource Blah[$some_title] cannot override local resource on node $nodename
While this is not a classic “syntax” error, it is a annoying error none-the-less. The actual error tells you that you have a local resource Blah[$some_title] that puppet refuses to overwrite with a collected resource of the same name. What most often happens, that the same resource is exported by two nodes. One of them is collected first and when trying to collect the second resource, this error happens as the first is already converted to a “local” resource.
Common Misconceptions
Node Inheritance and Variable Scope
It is generally assumed that the following will result in the /tmp/puppet-test.variable file containing the string ‘my_node’:
class test_class {
file { "/tmp/puppet-test.variable":
content => "$testname",
ensure => present,
}
}
node base_node {
include test_class
}
node my_node inherits base_node {
$testname = 'my_node'
}
Contrary to expectations, /tmp/puppet-test.variable is created with no contents. This is because the inherited test_class remains in the scope of base_node, where $testname is undefined.
Node inheritance is currently only really useful for inheriting static or self-contained classes, and is as a result of quite limited value.
A workaround is to define classes for your node types – essentially include classes rather than inheriting them. For example:
class test_class {
file { "/tmp/puppet-test.variable":
content => "$testname",
ensure => present,
}
}
class base_node_class {
include test_class
}
node my_node {
$testname = 'my_node'
include base_node_class
}
/tmp/puppet-test.variable will now contain ‘my_node’ as desired.
Class Inheritance and Variable Scope
The following would also not work as generally expected:
class base_class {
$myvar = 'bob'
file {"/tmp/testvar":
content => "$myvar",
ensure => present,
}
}
class child_class inherits base_class {
$myvar = 'fred'
}
The /tmp/testvar file would be created with the content ‘bob’, as this is the value of $myvar where the type is defined.
A workaround would be to ‘include’ the base_class, rather than inheriting it, and also to strip the $myvar out of the included class itself (otherwise it will cause a variable scope conflict – $myvar would be set twice in the same child_class scope):
$myvar = 'bob'
class base_class {
file {"/tmp/testvar":
content => "$myvar",
ensure => present,
}
}
class child_class {
$myvar = 'fred'
include base_class
}
In some cases you can reset the content of the file resource so that the scope used for the content (e.g., template) is rebound. Example:
class base_class {
$myvar = 'bob'
file { "/tmp/testvar":
content => template("john.erb"),
}
}
class child_class inherits base_class {
$myvar = 'fred'
File["/tmp/testvar"] { content => template("john.erb") }
}
(john.erb contains a reference like <%= myvar %>.)
To avoid the duplication of the template filename, it is better to sidestep the problem altogether with a define:
class base_class {
define testvar_file($myvar="bob") {
file { $name:
content => template("john.erb"),
}
}
testvar_file { "/tmp/testvar": }
}
class child_class inherits base_class {
Base_class::Testvar_file["/tmp/testvar"] { myvar => fred }
}
Whilst not directly solving the problem also useful are qualified variables that allow you to refer to and assign variables from other classes. Qualified variables might provoke alternate methods of solving this issue. You can use qualified methods like:
class foo {
$foovariable = "foobar"
}
class bar {
$barvariable = $foo::foovariable
}
In this example the value of the of the $barvariable variable in the bar class will be set to foobar the value of the $foovariable variable which was set in the foo class.
Custom Type & Provider development
err: Could not retrieve catalog: Invalid parameter ‘foo’ for type ‘bar’
When you are developing new custom types, you should restart both the puppetmasterd and the puppetd before running the configuration using the new custom type. The pluginsync feature will then synchronise the files and the new code will be loaded when both daemons are restarted.