Change the period between these sentences to a dash:
... and by looking at three of the most common resource types β packages, files, and services. You will see how to find out the attributes that are available to a resource and how to declare a state.
can be written as,
... and by looking at three of the most common resource types--packages, files, and services--you will discover the attributes available to a resource and how to declare a state.
The class resource declaration has one typo:
- Line 2:
paramter1 => 'value1',
should instead be:parameter1 => 'value1',
π The bulleted list for the defined type declaration differs from the class declaration from the previous page. Suggestion: do not parenthetically identify the opening and closing elements.
Example:
- The
define
keyword - The name of the defined type
- Parameters within ()
- Type definition code within {}
define exampledefine (
String user = "${title}",
String group,
) {
user { ${user}: }
group { ${group}: }
file { '/export/home/${user}/.examplesetting':
user => ${user},
group => ${group},
content => "User is ${user} and group is ${group}",
}
}
The sentence,
This example has its dangers since if the second declaration for
user2
also used a group ofgroup1
, this would result in a duplicated resource declaration.
can be written to add emphasis to the word 'also' to make it clear to the reader that this is a hypothetical situation and is not a comment on how the example code above it is written.
Example,
This example has its dangers. If the declaration for
user2
also usedgroup1
, this would result in a duplicated resource declaration forgroup1
.
In the sentence that ends,
... prioritizing conflict between resources.
'conflict' should be either 'conflicts' or 'a conflict'.
π
Each resource will have a type ...
Can be written,
Each resource has a type ...
As with the defined type introduction, the formatting could more closely match the class formatting:
- Open with the resource type, such as
file
, with no quotes and lowercase - An open brace {
- The title of the resource in quotes
- A colon :
- A list of attribute name/value pairs separated with
=>
and ending with a comma , - A closing brace }
The code example has one typo:
- Line 7:
name => "$apach_package_name",
should instead bename => $apache_package_name,
π The example can rewritten to use the os.family
fact with 'Red Hat', formatted to match the Puppet style guide, and comply with stricter linting.
$apache_package_name = $facts['os']['family']? {
'Red Hat' => 'httpd',
default => 'apache2',
}
package { 'apache':
ensure => latest,
name => $apache_package_name,
}
π The sentence,
This sets several attributes to defaults, resulting in using the default provider for the underlying operating system, such as yum for Red Hat or, for Windows, the Windows provider ...
could be written,
This sets several attributes to defaults, resulting in using the default provider for the underlying operating system, such as
yum
ordnf
for Red Hat or thewindows
provider for Windows ...
The reference to .bin
should instead be .msi
.
Red Hat Enterprise Linux 8+ and distributions based on RHEL 8 cannot install the cowsay
package without first enabling EPEL.
The sentence,
To create and enforce a resource, we must select the value of a file and use
direct
to create a directory or directory nest orlink
to create a symbolic link.
Contains one typo: direct
should be directory
. In addition, the term "directory nest" is uncommon and should be "nested directories."
The example file
resource has incorrect spacing for the resource title, quotes the ensure
value, and uses back slashes instead of forward slashes for the path
value.
It should be formatted as:
file { 'Puppet directory':
ensure => directory,
path => 'C:/ProgramData/PuppetLabs',
}
The example file
resource has hash rockets that are not aligned and the content has inconsistant spacing.
It should be formatted as follows:
file { 'Example config':
ensure => file,
path => '/app/exampleapp/config.txt',
owner => 'exampleapp',
group => 'examplegroup',
content => "verbose = true\nselinux = permissive",
}
The statement,
... the comparative nature of Puppet, which uses
md5
checksums for content, ...
As of Puppet 7, the default digest algorithm is SHA256. See PUP-10583.
The statement,
The
purge
parameter can only be used withensure
set todirectory
orrecursive
set totrue
...
Should read,
The
purge
parameter can only be used withensure
set todirectory
orrecurse
set totrue
...
Or follow the Puppet 8 documentation entry:
[The
purge
] option only makes sense whenensure => directory
andrecurse => true
.
The recurse
example has incorrect spacing and ensure => directory
does not need to be quoted. It should be formatted as follows:
file { 'Remove apache config files outside of puppet control':
ensure => directory,
purge => true,
recurse => true,
path => '/etc/httpd/conf',
}
The target
example has incorrect spacing and is missing quotes for the path
and target
values. Capitalization for "Python" and "RHEL" added with formatting as follows:
file { 'Picking a Python on RHEL 8':
ensure => link,
path => '/usr/bin/python3',
target => '/usr/bin/python',
}
The following is not a correction; however, the Puppet language style guide would format the source
example thus,
file { '/etc/exampleapp.conf':
source => [
"nfsserver:///exampleapp/conf.${host}",
"nfsserver:///exampleapp/conf.${operatingsystem}",
'nfsserver:///exampleapp/conf',
]
}
The statement,
The replace parameter should be used sparingly, but if set to
true
, allows for a file to have content enforced only if it does not exist. If the file exists, the state is met. This can be useful for applications that require an initial configuration file but then overwrite it.
Should read,
Use the
replace
parameter sparingly. If set tofalse
it allows a file to have content enforced only if it does not exist.
From the Puppet 8 documentation:
replace
Whether to replace a file or symlink that already exists on the local system but whose content doesn't match what the
source
orcontent
attribute specifies. Setting this to false allows file resources to initialize files without overwriting future changes. Note that this only affects content; Puppet will still manage ownership and permissions.
For the service
example, the values for enable
do not need to be quoted and should be formatted as follows:
service { 'wuauserv':
ensure => running,
enable => delayed,
logonaccount => 'LocalSystem',
}
service { 'bam':
ensure => stopped,
enable => false,
}
The statement,
Comparing this to
systemd
, the default provider for RHEL 8 and other Linux systems, we can see in the description under supported features thatsystemctl
does not have delayed login ormanual
but does havemask
, which, in system terms, means it disables the service so not even services that are dependent on it can activate it.
Should read (correct 'in system terms' to 'in systemd
terms'),
Comparing this to
systemd
, the default provider for RHEL 8 and other Linux systems, we see in the description under supported features thatsystemctl
does not have delayed login ormanual
but does havemask
, which, insystemd
terms, means it disables the service so not even services that are dependent on it can activate it.
The formatting for the legacy service example should be:
service { 'legacy service':
ensure => running,
enable => true,
start => '/opt/legacyapp/startlegacy -e production',
stop => '/opt/legacyapp/stoplegacy -e production',
status => '/opt/legacyapp/legacystatus -e production',
}
There are two formatting corrections for the metaparameters
code example. There is no comma after the package name
attribute, the service
resource is declared with a capitalized 'S' and lacks a space following the opening brace. It should be formatted as follows:
package { 'example app package':
ensure => latest,
name => 'exampleapp',
before => File['example app configuration'],
}
file { 'example app configuration':
content => 'attribute=value',
notify => Service['example app service'],
}
service { 'example app service':
name => 'exampleapp',
enable => true,
ensure => running,
require => Package['example app package'],
}
The resource type dependency array example has two formatting corrections: there is an extra space in the resource title and no closing bracket for the array. In addition, the resource title or path
attribute should use forward slashes as recommended in the file resource documentation and should be formatted as:
file { 'C:/Program Files/Common Files/Example':
require => Package['package1', 'package2'],
}
In the statement,
The code can also be run in noop mode,
'mode' does not need to be in bold face.
The grafana.ini
code example uses upper case key names; however, the Grafana documentation use only lower case key names. It should be formatted as:
[server]
protocol = HTTP
http_port = 8080
There is a formatting error in the closing paragraph under the sub heading "User and group types".
<name of computer\<user name>
Should be,
<name of computer>\<user name>
The code formatting for the statement,
So, for example,
'DESKTOP-1MT10AJ\david
,'BUILTIN\david'
anddavid
are all treated the same by Puppet.
Is inconsistent with missing single quotes for the first and third user names and should be formatted as:
So, for example,
'DESKTOP-1MT10AJ\david'
,'BUILTIN\david'
and'david'
are all treated the same by Puppet.
The Windows and Unix account and group code example contains a number of formatting errors and should be formatted as follows. I have reformatted the arrays so they are not on a single line and match the Puppet language style guide.
user { 'david':
ensure => present,
groups => [
'BUILTIN\Administrators',
'BUILTIN\Users',
],
}
group { 'Users':
ensure => present,
members => [
'NT AUTHORITY\INTERACTIVE',
'NT AUTHORITY\Authenticated Users',
'DESKTOP-1MT10AJ\david',
],
}
user { 'ubuntu':
ensure => present,
comment => 'Ubuntu',
gid => 1000,
groups => [
'adm',
'dialout',
'cdrom',
'floppy',
'sudo',
'audio',
'dip',
'video',
'plugdev',
'lxd',
'netdev',
],
home => '/home/ubuntu',
password => '!',
password_max_age => 99999,
password_min_age => 0,
password_warn_days => 7,
shell => '/bin/bash',
uid => 1000,
}
group { 'ubuntu':
ensure => present,
gid => 1000,
}
π The statement,
We can achieve this if the command itself is already idempotent, such as
apt-get update
...
apt-get update
is arguably not idempotent as the command updates a catalog file after every run and may exit with a non-zero status.
In the paragraph,
In the first case, if the command is idempotent, it will do no harm, but it will log in each Puppet run that it has run, and therefore using the other two methods is better to avoid the exec reporting runs.
It should reference "the other three methods ..." (onlyif
, unless
, and creates
). If the language of the paragraph is referring to the use of onlyif
then it should make it clear that "the first case" is onlyif
.
In the exec
code example for disabling public Chocolatey access, the hash rockets do not align. Indentation for both exec
examples differ (pages 53 and 54). One use four spaces, the other uses three.
There are too many spaces for the third exec
code scenario. The example should be formatted as follows:
exec { 'refresh exampleapp configuration':
command => '/bin/exampleapp/rereadconfig',
refreshonly => true,
subscribe => File['config file'],
}
file { 'config file':
path => '/etc/exampleapp/configfile',
content => 'setting 1 = value',
}
There is no Puppet version 7.9+ as referenced in the statement,
On Unix platforms, a recent feature called parametrized execs was introduced with Puppet 6.24+ and 7.9+ ...
I have not yet identified which 7.2+ (presumably) release added parameterized exec
.
The parameterized exec
code example has a typo for 'parameterized', has too many spaces and does not include a colon after the resource title.
The example should be formatted as follows:
exec { 'parameterized command':
command => ['/bin/echo', 'real parameters; rm -rf /'],
}
The Augeas code example has too many spaces and the resource type should be lower case. It should be formatted as follows:
augeas { 'remove John from access.conf':
changes => 'rm /files/etc/security/access.conf/*[user="john"]',
}
π The notify
code example should have a space prior to the closing brace, as follows,
notify { 'print a message to logs': }
The audit
code example has too many spaces and the resource title does not end with a colon. It should be formatted as follows:
file { '/var/tmp/example':
mode => '0770',
audit => [owner,group],
}
The example code for tag
has too many spaces before the hash rockets, the value for ensure
need not be quoted. It should be formatted as follows:
class example::access {
group { 'ubuntu':
ensure => present,
gid => 1000,
tag => ['pci','sox'],
}
user { 'ubuntu':
ensure => present,
tag => 'pci',
}
}
The resources
metatype code example does not follow the Puppet language style guide for spacing the resource title. It should be formatted as follows:
resources { 'user':
purge => true,
noop => true,
}
Spacing in the array of titles code example is invalid and does not match the style guide. It should be formatted as follows:
file { ['/opt/example1','/opt/example1/etc','/opt/example1/bin']:
owner => 'user',
group => 'user',
mode => '0750',
}
The overriding parameters code example has too many spaces before the hash rockets and no space between File
and the overridden resource title. It should be formatted as follows:
File ['/opt/example/bin/'] {
group => 'other_group',
audit => true,
}
Indentation for the example case
statement for the splat attribute is inconsistent; there are too many spaces before the hash rockets; the splat attribute references a brace-enclosed variable when it should not; and the quoted strings should use single quotes instead of double quotes. It should be formatted as follows:
case $facts['os']['name'] {
/^(Debian|Ubuntu)$/: {
$package_options = {
'name' => 'apache2'
}
}
default: {
$package_options = {
'name' => 'httpd'
}
}
}
package { 'http':
ensure => latest,
* => $package_options,
}
The statement,
This results in the package
http
resource using the namehttp2
for Ubuntu and Debian systems ...
Should be,
This results in the package
http
resource using the nameapache2
for Ubuntu and Debian systems ...
In the lab, the instruction,
As a second exercise, create a separate manifest to create some users on the Linux client,
linux_users.pp create 3 users exampleappdev, exampleapptest, exampleappprod
, and a group,exampleapp
, with all the users using this group as their primary group.
Should be,
As a second exercise, create a separate manifest to create some users on the Linux client,
linux_users.pp
. Create three users:exampleappdev
,exampleapptest
, andexampleappprod
. Create the groupexampleapp
with all three users using this group as their primary group.
The code example for the abstract resource type references an undeclared variable, uses resource
instead of Resource
, and uses incorrect quoting that results in an unexpected end of file error.
It should be formatted as follows:
$mytype = exec
Resource[$mytype] { '/bin/echo "don\'t use this" > /tmp/badidea':
creates => '/tmp/badidea',
}
Likewise, the simple translation should be formatted as follows:
exec { '/bin/echo "don\'t use this" > /tmp/badidea':
creates => '/tmp/badidea',
}
π In the code example for the default:
resource body, one array ends with a comma but the other does not.
The code example for the "Resource default syntax" uses a lower case 'f' for file
instead of the upper case File
as well as too many spaces before the hash rockets. The example should be formatted as follows:
File {
owner => 'exampleapp',
group => 'exampleapp',
mode => '0660',
}
The schedule
code examples also have too many spaces before or within the hash rockets and should be formatted as follows:
schedule { 'Friday Night':
day => 'Friday',
range => '18 - 9',
}
exec { '/bin/echo weekend start > /tmp/example':
schedule => 'Friday Night',
}
π The statement in the first paragraph under the "Exporters and collectors" has this statement,
This is done by exporting the information to the PuppetDB database, which Puppet runs will consult with when collecting.
I would make the sentence more clear by adding 'resources' to the end of the sentence:
This is done by exporting the information to the PuppetDB database, which Puppet runs will consult with when collecting resources.
π The statement,
Exporting a resource just involves adding
@@
in front of a normal resource declaration.
Can be,
Exporting a resource requires adding
@@
in front of a normal resource declaration.
The code example for exporting resources references a legacy fact and has too many spaces before the hash rockets. It should be formatted as follows:
@@host { "Oracle database host entry ${trusted['hostname']}" :
name => 'dbserver1',
ip => '192.168.0.6',
tag => 'oracle',
}