Errata

Learning Puppet 4

Errata for Learning Puppet 4

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Chapter 2: Downloading a Box

In the book, the code snippet to have Vagrant add the Puppetlabs CentOS 7 box points to their 7.0 box on Atlas:

`vagrant box add --provider virtualbox puppetlabs/centos-7.0-64-nocm`

In your latest rev of the Vagrant file on the Github project, it has us downloading the newer CentOS 7.2 box:

`Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "puppetlabs/centos-7.2-64-nocm"`

Just wanted to bump the version of the box users are to add from 7.0 to 7.2.

Thanks!

Note from the Author or Editor:
Fixed in October, 2016 update.

Austin Grice  Mar 24, 2016  Feb 09, 2018
PDF
Page xxix
last paragraph

In the last paragraph, Kanies is misspelled "Kaines".

Note from the Author or Editor:
Fixed in October, 2016 update.

Anonymous  Apr 15, 2016  Feb 09, 2018
NA
NA

In chapter 5, section "Using Comparison Operators", I found the following statement:

"String equality comparisons are case insensitive, while substring matches are case sensitive".

I found the latter portion of this statement to be false.

For instance, the following two expressions should both return "false" if that statement was true:
-------------------------
[vagrant@client ~]$ puppet apply -e 'notice("f" in "FOO"); notice("Fee" in "coffee")'
Notice: Scope(Class[main]): true
Notice: Scope(Class[main]): true
---------------------

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 13, 2016  Feb 09, 2018
NA
NA

In chapter 5, section "Using Comparison Operators", I found some sample code that fails to compile.

The text with the erroneous code is the following:
--------------------------
'tea' !in 'coffee' # you can't find tea in coffee
'Fee' !in 'coffee' # substring matches are case sensitive
--------------------------

The "!in" operator is invalid. The "!" has to surround the entire expression, like this:
--------------------
!('tea' in 'coffee') # you can't find tea in coffee
!('Fee' in 'coffee') # substring matches are case sensitive
----------------

When the original expression is executed, it fails like this:
---------------
[vagrant@client ~]$ puppet apply -e 'notice("tea" !in "coffee")'
Error: Could not parse for environment production: Syntax error at '!' at line 1:14 on node client.example.com
----------------

But the following works:
------------------
[vagrant@client ~]$ puppet apply -e 'notice(!("tea" in "coffee"))'
Notice: Scope(Class[main]): true
---------------------------

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 13, 2016  Feb 09, 2018
NA
NA

In chapter 5, in section "Using Variables in Resources", where it describes the trick of retrieving hash entries of a particular key by assigning to an array with variables whose name represents the key to search for, there is a problem with the variable used.

You demonstrate this feature with the following:
------------------
[$Jack] = $homes # identical to $Jack = $homes['Jack']
------------------

Earlier in the book, in the "Defining Variables" section, it clearly states that "The variable name must start with a lowercase letter or underscore". I didn't actually verify this, but I assume that either that statement is wrong, or the example is.

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 13, 2016  Feb 09, 2018
NA
NA

In chapter 8, section "Enhancing Older Manifests", subsection "Using Hash and Array Literals", there is the following code sample:
-----------------
notify { "(['one','two','three'][1] )": } # produces the output "two"
-----------------

Actually, this produces the output "(['one','two','three'][1] )".

Removing the surrounding double quotes, like this:
-----------------
notify { (['one','two','three'][1] ): } # produces the output "two"
-----------------

does result in the output "two".

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 16, 2016  Feb 09, 2018
NA
NA

In chapter 13, section "Understanding Module Structure", the first sentence says "Let’s review the files and directories created in your new module."

The table provided here has the following entries:
-------------------------
manifests/ Directory where code manifests (classes) are read.
files/ Directory containing files served by your module.
templates/ Directory containing templates parsed for custom files.
lib/ Directory containing Ruby facts or functions.
specs/ Directory containing unit tests to validate the manifests.
tests/ Directory containing system tests to validate the manifests.
facts.d/ Directory containing external facts to be distributed.
metadata.json File containing version and module dependencies.
-----------------------

In the previous section, where we created the module, the book content itself shows what was created (omitting file names in subdirs):
--------------------
Notice: Generating module at /home/vagrant/puppet...
Notice: Populating templates...
Finished; module generated in puppet.
puppet/manifests
puppet/spec
puppet/tests
puppet/Gemfile
puppet/Rakefile
puppet/README.md
puppet/metadata.json
--------------------

As you can see, there are several differences between what the book says would have been created and what was actually created. Most of the differences are files/dirs present in one that aren't in the other, but one says "spec" and the other says "specs".

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 17, 2016  Feb 09, 2018
NA
NA

Chapter 13, section "Using Puppet EPP Templates".

The following is an excerpt of the code sample that shows the "epp" function call:
--------------------
content => epp('puppet/puppet.conf.epp'),
--------------------

The following is the text that comes after this, that describes the first of the two possible parameters to the "epp" function:
-------------------
URI of the Puppet EPP template
The format of that URI is always puppet:///modulename/filename.epp. The file should be placed in the templates/ directory of the module. Puppet EPP templates should end with the .epp extension to indicate that the file contains tags for the Puppet EPP template processor.
---------------------

Note that the description of the format of the parameter doesn't match the example. According to the official documentation, at https://docs.puppet.com/puppet/latest/reference/function.html#epp , the code sample is correct, and the parameter description is incorrect.

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 19, 2016  Feb 09, 2018
NA
NA

Chapter 13, section "Using Puppet EPP Templates".

Along the lines of the earlier issue with the format of the first parameter to the "epp()" function, I note the following code sample in the "Providing parameters" subsection:
-----------------
content => epp('puppet:///puppet/puppet.conf.epp', {
'server' => $server,
'common_loglevel' => $common_loglevel,
'agent_loglevel' => $agent_loglevel,
'apply_loglevel' => $apply_loglevel,
}),
----------------

As somewhat expected, this fails with:
---------------------
[vagrant@client puppet]$ sudo puppet apply --environment test manifests/init.pp
Notice: Scope(Class[Puppet]): Install the latest version of Puppet, ensure it's running, and set boot time start true.
Error: Evaluation Error: Error while evaluating a Function Call, Could not find template 'puppet:///puppet/puppet.conf.epp' at /etc/puppetlabs/code/environments/test/modules/puppet/manifests/init.pp:85:14 on node client.example.com
----------------

Changing it back to the original format of "puppet/puppet.conf.epp" makes it work.

Note from the Author or Editor:
Fixed in October 2016 update.

David M. Karr  May 19, 2016  Feb 09, 2018
NA
NA

In chapter 14, section "Tracking Resource Defaults Scope", there is the following text about determining the "parent scope":
----------------------
This means that the parent class will be the class which declared this class if the class does not inherit from another class. Read that sentence twice, carefully.

* If a class is declared within another class, then the parent scope is the calling class.
* If a class inherits from another class, then the parent scope is the inherited class.
-----------------------

If the first statement is true, then the two list items should be reworded to something like this:
-----------------
* If a class inherits from another class, then the parent scope is the inherited class.
* If not, and the class is declared within another class, then the parent scope is the calling class.
---------------

If that first statement is not completely accurate, then perhaps it needs to change, not the two list items. In any case, one of them is definitely wrong.

The point is, if the rule is defined by the two list items, then a class that is declared within another class that ALSO inherits from another class, then the parent scope is the defining, or "calling" class. If the first statement is true, however, then the parent scope is the inherited class.

Note from the Author or Editor:
I have changed the wording around this for the February 2018 update.

David M. Karr  May 20, 2016  Feb 09, 2018
NA
NA

Chapter 14, section "Containing Classes".

The first code sample is this:
------------------
service 'dependency' {
ensure => running,
after => Class['only_has_variables']
}
------------------

I think this is just a rhetorical example, but I would think a more correct syntax would be this:
------------------
service { 'dependency':
ensure => running,
after => Class['only_has_variables']
}
-------------

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 26, 2016  Feb 09, 2018
NA
NA

Chapter 14, section "Creating Reusable Modules".

There are several invalid code samples on this page, all using a pattern like this:
--------------
type 'name' {
stuff ...
}
------------

They should all be:
--------------
type { 'name':
stuff ...
}
--------------

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 26, 2016  Feb 09, 2018
NA
NA

Chapter 15, section "Creating Puppet Types".

Several code samples on this page use the "defaulto" keyword to set a default value. It appears that this is supposed to be "defaultto" (it's odd that they didn't just call it "default").

Note from the Author or Editor:
Fixed in October, 2016 update.

David M. Karr  May 26, 2016  Feb 09, 2018
NA
Chapter 14: Looking up input from hiera

The yaml file is incorrect. It shouldn't have an equal to "=" sign.

--
classes:
- puppet

puppet::version = 'latest'
puppet::status = 'stopped'
puppet::enabled = false

Note from the Author or Editor:
Fixed in the February 2018 update.

Charan Ramireddy  Dec 19, 2016  Feb 09, 2018
13
Parsing Templates paragragh

Under this block, it says ensure => ensure. It should infact be ensure => file

Using Puppet EPP TemplatesAdjust the file declaration from the previous section to remove the source attribute and replace it with a content attribute. The content will be provided by the epp() function:

file { '/etc/puppetlabs/puppet/puppet.conf':
ensure => ensure,
owner => 'root',
group => 'wheel',
mode => '0644',
content => epp('puppet/puppet.conf.epp'),
}

Note from the Author or Editor:
Fixed in February 2018 update.

Charan Ramireddy  Dec 16, 2016  Feb 09, 2018
PDF
Page 21
3rd paragraph that begins, "Now that this is running..."

When turning up the first Vagrant host "client," no password is specified in the book but a password is required to authenticate. I'm using Macintosh.

Steps to replicate this problem:
1. install Vagrant
2. install VirtualBox
3. Install XCode
4. vagrant plugin install vagrant-vbguest
5. vagrant up client
6. vagrant ssh client

Note from the Author or Editor:
Adjusted to reflect changes in Vagrant in October, 2016 update.

Andrew  Aug 18, 2016  Feb 09, 2018
27
Chapter 27: Configuring Puppet Dashboard - last command

The last command you give, to put the secret token in settings.yml, is

[puppet-dashboard@dashserver ~]$ echo "secret_token: \
'$(bundle exec rake secret)'" > config/settings.yml

That overwrites settings.yml with the secret token. I think you meant

[puppet-dashboard@dashserver ~]$ echo "secret_token: \
'$(bundle exec rake secret)'" >> config/settings.yml

Note from the Author or Editor:
Fixed in October, 2016 update.

Kevin McKenzie  May 09, 2016  Feb 09, 2018
PDF
Page 43
3rd paragraph

In Managing Files section, it says "This is a properly declarative policy"

I feel it should be "This is (a proper)/(the recommended) declarative policy".

Note from the Author or Editor:
Fixed in October, 2016 update.

Gaurav Chhabra  Apr 15, 2016  Feb 09, 2018
Printed,
Page 69
Example code at end of page

if( $facts['osfamily'] == 'redhat' ) {

Should read

if( $facts['osfamily'] == 'RedHat' ) {

This error is repeated with the other osfamily values where characters in the names are uppercase.

The line:
and ( $facts['os']['release']['major'] >= 9

will not work as this fact is a string and NOT a number so the code produces a syntax error .

same errors repeated on page 70

Note from the Author or Editor:
The conversion to Integer has been fixed in the February 2018 update.

The equals operator for String comparison is case insensitive ;)

Mike Phillips  Jan 25, 2017  Feb 09, 2018
PDF
Page 75
3rd line

At the start of page 75, it says,

The following manifest would provide the exact same results:
each( $facts['system_uptime'] ) |$uptime| {
notice( "System has been up $uptime[1] $uptime[0]" )
}

Above code has a minor issue of missing curly braces in variable $uptime[1] and $uptime[0]. Without those curly braces, output is not correct.

It should be ${uptime[1]} and ${uptime[0]}

Note from the Author or Editor:
Fixed in February 2018 update.

GC  Nov 07, 2016  Feb 09, 2018
PDF, ePub, Mobi
Page 116
line 4 & line 6

Line 4:
$ puppet apply upgrade/manifests/site.pp --environment=future --noop

should be
$ puppet apply upgrade/manifests/site.pp --environment=upgrade --noop


Line 6:
$ puppet agent --test --environment=future --noop

should be
$ puppet agent --test --environment=upgrade --noop


Note from the Author or Editor:
Fixed for the February 2018 update.

Andrew Elwell  Dec 17, 2016  Feb 09, 2018
Mobi
Page 137
2nd paragraph

"we have a special local user, Jane. As we only want to change the user’s home directories, we might create a higher-priority hostname/clients.yaml file with just the differences:
# hostname/client.yaml
"
Rhett, Jo. Learning Puppet 4: A Guide to Configuration Management and Automation (p. 137). O'Reilly Media. Kindle Edition.

The hostname/clients.yaml should be hostname/client.yaml I believe.

Note from the Author or Editor:
Fixed in October, 2016 update.

Anonymous  May 20, 2016  Feb 09, 2018
Printed
Page 153
"Assigning Modules to Nodes" section

The book says "Back in Chapter 10, we set up a manifest in each environment to load classes form Hiera". There is no mention of this in Chapter 10 and the first mention of it I find is on the next page in the "Using Hiera for Module Assignment" subsection, which starts on page 153 and continues on page 154.

Note from the Author or Editor:
I have changed the wording around this for the February 2018 update.

Mark Berthiaume  Dec 08, 2016  Feb 09, 2018
PDF
Page 311
Under "Running Acceptance Tests"

There aren't any acceptance test files in the custom module skeleton that readers create in. This creates an issue in Chapter 17 when, to run acceptance test:

$ rspec spec/acceptance

will fail with:

/home/vagrant/.gem/ruby/gems/rspec-core-3.4.3/lib/rspec/core/configuration.rb:1361:in `load': cannot load such file -- /etc/puppetlabs/code/environments/test/modules/puppet/spec/acceptance (LoadError)

because it does not exist. The structure as outlined in the PDF until that point is as below:

$ tree
.
├── files
│   └── puppet.conf
├── Gemfile
├── Gemfile.lock
├── manifests
│   └── init.pp
├── metadata.json
├── Rakefile
├── README.md
├── spec
│   ├── classes
│   │   ├── init_spec.rb
│   │   └── puppet_spec.rb
│   ├── fixtures
│   │   ├── manifests
│   │   └── modules
│   └── spec_helper.rb
└── tests
└── init.pp

I cannot find the files in the Github repo either to facilitate acceptance testing.

Note from the Author or Editor:
4 sections of the book were not included in the push for some reason. We have added these pages back, so the next push of the book and the final printed copy will contain instructions for creating the tests.

Anonymous  Mar 03, 2016  Mar 22, 2016