The document discusses Nick Fagerlund's exploration of the Puppet language and documentation during a PuppetConf event. Some key points discussed include:
- Nick found the initial language tutorial to be disorganized and that the language and documentation evolved over time in an ad hoc manner.
- Through experimenting with Puppet code, Nick discovers differences between equality operators ("==" vs "==") and different syntaxes for referencing resources (multi-references vs arrays).
- The post also explores searching and including classes, namespaces, and the preference for including classes explicitly rather than relying on automatic inheritance.
12. puppetconf.com #puppetconf
@notify
{'one
tag':
tag
=>
'one',
}
@notify
{'two
tags':
tag
=>
['one',
'two'],
#before
=>
Notify['three
tags']
}
@notify
{'three
tags':
tag
=>
['one',
'two',
'three'],
noop
=>
undef,
}
Let’s talk about collectors
Friday, August 23, 13
13. puppetconf.com #puppetconf
Notify
<|
tag
==
'one'
|>
Notice:
Compiled
catalog
for
magpie.lan
in
environment
production
in
0.11
seconds
Notice:
one
tag
Notice:
/Stage[main]//Notify[one
tag]/message:
defined
'message'
as
'one
tag'
Notice:
three
tags
Notice:
/Stage[main]//Notify[three
tags]/message:
defined
'message'
as
'three
tags'
Notice:
two
tags
Notice:
/Stage[main]//Notify[two
tags]/message:
defined
'message'
as
'two
tags'
Let’s talk about collectors
Friday, August 23, 13
14. puppetconf.com #puppetconf
Notify
<|
'one'
==
tag
|>
Error:
Could
not
parse
for
environment
production:
Syntax
error
at
'one';
expected
'|>'
at
/Users/nick/Documents/
manifests/collector-‐search.pp:29
on
node
magpie.lan
Let’s talk about collectors
Friday, August 23, 13
15. puppetconf.com #puppetconf
Notify
<|
tag
==
['one',
'two']
|>
Notice:
Compiled
catalog
for
magpie.lan
in
environment
production
in
0.09
seconds
Notice:
one
tag
Notice:
/Stage[main]//Notify[one
tag]/message:
defined
'message'
as
'one
tag'
Notice:
three
tags
Notice:
/Stage[main]//Notify[three
tags]/message:
defined
'message'
as
'three
tags'
Notice:
two
tags
Notice:
/Stage[main]//Notify[two
tags]/message:
defined
'message'
as
'two
tags'
Notice:
Finished
catalog
run
in
0.17
seconds
Let’s talk about collectors
Friday, August 23, 13
16. puppetconf.com #puppetconf
Notify
<|
tag
!=
['one',
'two']
|>
Notice:
Compiled
catalog
for
magpie.lan
in
environment
production
in
0.09
seconds
Notice:
three
tags
Notice:
/Stage[main]//Notify[three
tags]/message:
defined
'message'
as
'three
tags'
Notice:
two
tags
Notice:
/Stage[main]//Notify[two
tags]/message:
defined
'message'
as
'two
tags'
Notice:
Finished
catalog
run
in
0.18
seconds
Let’s talk about collectors
Friday, August 23, 13
20. puppetconf.com #puppetconf
class
class
{
notify
{'hey
it
worked':}
}
include
class
Error:
Could
not
parse
for
environment
production:
Syntax
error
at
'class'
at
/
Users/nick/Documents/manifests/
class_class.pp:6
on
node
magpie.lan
Classy
Friday, August 23, 13
22. puppetconf.com #puppetconf
class
class
{
notify
{'hey
it
worked':}
}
include
"class"
Notice:
Compiled
catalog
for
magpie.lan
in
environment
production
in
0.09
seconds
Notice:
hey
it
worked
Notice:
/Stage[main]/Class/Notify[hey
it
worked]/message:
defined
'message'
as
'hey
it
worked'
Notice:
Finished
catalog
run
in
0.19
seconds
Classy
Friday, August 23, 13
23. puppetconf.com #puppetconf
class
parent
{
define
doessomething
{
notice("parentvar
is
set,
in
the
parent::doessomething
define")
}
class
whoa
{
notice("Okay
that
works
w/
classes
too")
}
$otherparentvar
=
"haha
whoa"
}
search('parent')
doessomething{'something':}
include
whoa
notice($otherparentvar)
#
This
one
doesn't
work
though,
because
it
attaches
the
NAMESPACE,
not
the
scope.
Search???
Friday, August 23, 13
24. puppetconf.com #puppetconf
class
parent
{
define
doessomething
{
notice("parentvar
is
set,
in
the
parent::doessomething
define")
}
class
whoa
{
notice("Okay
that
works
w/
classes
too")
}
$otherparentvar
=
"haha
whoa"
}
search('parent')
doessomething{'something':}
include
whoa
notice($otherparentvar)
#
This
one
doesn't
work
though,
because
it
attaches
the
NAMESPACE,
not
the
scope.
It
dumps
a
random
namespace
into
the
local
namespace???
Search???
Friday, August 23, 13
29. puppetconf.com #puppetconf
#
OK
require
=>
Notify['first',
'second']
require
=>
[
Notify['first'],
Notify['second']
]
Notify['first',
'second']
-‐>
Notify['third']
#
BAD
[
Notify['first'],
Notify['second']
]
-‐>
Notify['third']
?????!!
They all look kind of similar?
Friday, August 23, 13
30. puppetconf.com #puppetconf
#
OK
Notify['first',
'second']
{
message
=>
'Adding
a
message
to
these.'
}
#
BAD
[
Notify['first'],
Notify['second']
]
{
message
=>
'Adding
a
message
to
these.'
}
?????!!
They all look kind of similar?
Friday, August 23, 13
32. puppetconf.com #puppetconf
class
bar
{
notice("From
class
bar")
}
class
foo::bar
{
notice("From
class
foo::bar")
}
class
foo
{
include
bar
}
include
foo
Include bar... but only as a last
resort
Friday, August 23, 13
33. puppetconf.com #puppetconf
class
bar
{
notice("From
class
bar")
}
class
foo::bar
{
notice("From
class
foo::bar")
}
class
foo
{
include
bar
}
include
foo
Notice:
Scope(Class[Foo::Bar]):
From
class
foo::bar
(this
is
bug
#2053.)
Include bar... but only as a last
resort
Friday, August 23, 13
34. puppetconf.com #puppetconf
#
Is
the
==
operator
case-‐sensitive?
NO
notice(
'eat'
==
'EAt'
)
#
Is
the
'in'
operator
case-‐sensitive?
YES
notice(
'eat'
in
'EAten'
)
Notice:
Scope(Class[main]):
true
Notice:
Scope(Class[main]):
false
Case sensitivity training
Friday, August 23, 13
36. puppetconf.com #puppetconf
#
The
$is_virtual
fact
is
false
on
this
machine
if
$is_virtual
{
notice("Guess
this
is
a
virtual
machine!")
}
Falseness is truth
Friday, August 23, 13
37. puppetconf.com #puppetconf
#
The
$is_virtual
fact
is
false
on
this
machine
if
$is_virtual
{
notice("Guess
this
is
a
virtual
machine!")
}
Notice:
Scope(Class[main]):
Guess
this
is
a
virtual
machine!
Falseness is truth
Friday, August 23, 13
43. puppetconf.com #puppetconf
$x
=
5
$y
=
3
notice("Five
by
three
is
${$x
*
$y}")
Notice:
Scope(Class[main]):
Five
by
three
is
15
Express yourself
Friday, August 23, 13
44. puppetconf.com #puppetconf
$mystring
=
"Nothing
in
particular"
notice("But
it
was
${$mystring
=~
/thing/}")
Notice:
Scope(Class[main]):
But
it
was
true
Express yourself
Whoa
Friday, August 23, 13
45. puppetconf.com #puppetconf
notice("This
time
with
an
in
statement:
Is
there
a
thing
in
nothing?
${"thing"
in
$mystring}
so
yeah")
Notice:
Scope(Class[main]):
This
time
with
an
in
statement:
Is
there
a
thing
in
nothing?
true
so
yeah
Express yourself
Friday, August 23, 13
46. puppetconf.com #puppetconf
notice("There's
a
function
operand
in
here:
${
fqdn_rand(30)
+
'90'
}
so
yeah")
WELL,
at
least
THAT
one
doesn’t
work.
Express yourself
Friday, August 23, 13
47. puppetconf.com #puppetconf
notice("Variable
with
doubled
sigil:
${
$x}
so
yeah")
notice("Singular
sigil,
but
with
wacky
spacing:
${
x}
so
yeah")
Notice:
Scope(Class[main]):
Variable
with
doubled
sigil:
5
so
yeah
Notice:
Scope(Class[main]):
Singular
sigil,
but
with
wacky
spacing:
5
so
yeah
Express yourself
Friday, August 23, 13
48. puppetconf.com #puppetconf
notice("Yo
dawg,
I
heard
you
like
${"strings,
so
I
put
a
string
in
your"}
string")
Sorry
for
partying
like
it’s
200X,
but
anyway
yeah,
that
totally
works.
Express yourself
Friday, August 23, 13
49. puppetconf.com #puppetconf
#
What
about
this?
notice("Twenty
by
eighty
is
${
20
*
80
}
so
yeah")
Error:
left
operand
of
*
is
not
a
number
Express yourself
Friday, August 23, 13
50. puppetconf.com #puppetconf
notice("Twenty
by
eighty
is
${
'20'
*
'80'
}
so
yeah")
Notice:
Scope(Class[main]):
Twenty
by
eighty
is
1600
so
yeah
Express yourself
Friday, August 23, 13
52. puppetconf.com #puppetconf
(It turns out the first bareword in an
interpolation block gets silently
turned into a variable,so 20 became
$20,which would be a regex capture
variable except we weren’t inside a
conditional so it was undef???)
Friday, August 23, 13
56. puppetconf.com #puppetconf
file
{'file1':
path
=>
'/tmp/file1',
ensure
=>
file,
alias
=>
['othername',
'fourthname'],
}
file
{'file2':
path
=>
'/tmp/file2',
ensure
=>
file,
before
=>
File['othername'],
}
Let’s talk about aliases
Friday, August 23, 13
57. puppetconf.com #puppetconf
file
{'file1':
path
=>
'/tmp/file1',
ensure
=>
file,
alias
=>
['othername',
'fourthname'],
}
file
{'file2':
path
=>
'/tmp/file2',
ensure
=>
file,
before
=>
File['othername'],
}
This
works
fine.
Let’s talk about aliases
Friday, August 23, 13
58. puppetconf.com #puppetconf
file
{'file1':
alias
=>
['othername',
'fourthname'],
}
file
{'file2':}
File['file2']
-‐>
File['othername']
Error:
Could
not
find
resource
'File[othername]'
for
relationship
from
'File[file2]'
on
node
magpie.lan
So
it
works
in
metaparameters,
but
not
in
chaining
statements.
Okay!
Let’s talk about aliases
Friday, August 23, 13
59. puppetconf.com #puppetconf
@file
{'file1':
path
=>
'/tmp/file1',
ensure
=>
file,
alias
=>
['othername',
'fourthname'],
}
realize
File['othername']
Nope!
Let’s talk about aliases
Friday, August 23, 13
60. puppetconf.com #puppetconf
@file
{'file1':
path
=>
'/tmp/file1',
ensure
=>
file,
alias
=>
['othername',
'fourthname'],
}
realize
File['/tmp/file1']
Nope!
Let’s talk about aliases
Friday, August 23, 13
61. puppetconf.com #puppetconf
@file
{'file1':
path
=>
'/tmp/file1',
ensure
=>
file,
alias
=>
['othername',
'fourthname'],
}
File
<|
alias
==
'fourthname'
|>
PURRS
LIKE
A
KITTEN!
Let’s talk about aliases
Friday, August 23, 13