Nick’s DSL Quest:
WAT Safari
Nick Fagerlund
Technical Writer | Puppet Labs
@nfagerlund
Friday, August 23, 13
puppetconf.com #puppetconf
So okay,there I was.
Friday, August 23, 13
puppetconf.com #puppetconf
When I first got here,we
had this “language
tutorial.”
Friday, August 23, 13
puppetconf.com #puppetconf
It was a bit of
a mess.
(“Additional language
features…?”)
Friday, August 23, 13
puppetconf.com #puppetconf
The Puppet language
accreted over time.
Friday, August 23, 13
puppetconf.com #puppetconf
(And so did the docs.)
Friday, August 23, 13
puppetconf.com #puppetconf
So I had a good/bad idea.
Friday, August 23, 13
puppetconf.com #puppetconf
Here’s what I found.
Friday, August 23, 13
puppetconf.com #puppetconf
$subj	
  =	
  {t	
  =>	
  'r',	
  u	
  =>	
  'e'}
notice(str2bool("$subj"))
T to the R
Friday, August 23, 13
puppetconf.com #puppetconf
$subj	
  =	
  {t	
  =>	
  'r',	
  u	
  =>	
  'e'}
notice(str2bool("$subj"))
true
T to the R
Friday, August 23, 13
puppetconf.com #puppetconf
Friday, August 23, 13
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
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
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
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
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
puppetconf.com #puppetconf
CONCLUSION:
“==” != “==”
Friday, August 23, 13
puppetconf.com #puppetconf
Friday, August 23, 13
puppetconf.com #puppetconf
class	
  class	
  {
	
  	
  notify	
  {'hey	
  it	
  worked':}
}
include	
  class
Results
Classy
Friday, August 23, 13
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
puppetconf.com #puppetconf
class	
  class	
  {
	
  	
  notify	
  {'hey	
  it	
  worked':}
}
include	
  "class"
Classy
Friday, August 23, 13
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
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
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
puppetconf.com #puppetconf
(This is still in Puppet 3.2.)
(photo via http://
weheartit.com/entry/
68358166)
Friday, August 23, 13
puppetconf.com #puppetconf
[	
  Notify['first'],	
  Notify['second']	
  ]
It’s	
  an	
  array	
  of	
  resource	
  references,	
  right?
Have you seen this syntax?
Friday, August 23, 13
puppetconf.com #puppetconf
Notify[	
  'first',	
  'second'	
  ]
???
How about this one?
Friday, August 23, 13
puppetconf.com #puppetconf
Notify[	
  ['first',	
  'second']	
  ]
(Okay,	
  it	
  ends	
  up	
  being	
  the	
  same	
  as	
  the	
  last	
  one	
  for	
  some	
  
reason.)
How about this one?
Friday, August 23, 13
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
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
puppetconf.com #puppetconf
So,these are two
completely different
syntaxes. (I named the
non-array one “multi-
references.)
Friday, August 23, 13
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
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
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
puppetconf.com #puppetconf
ANYWAY
Friday, August 23, 13
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
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
puppetconf.com #puppetconf
(Use the str2bool()
function from
puppetlabs/stdlib)
Friday, August 23, 13
puppetconf.com #puppetconf
This,of course,escalated
quickly.
Friday, August 23, 13
puppetconf.com #puppetconf
Code
Results
What IS truth,anyway?
Friday, August 23, 13
puppetconf.com #puppetconf
$x	
  =	
  5
$y	
  =	
  3
notice("Value	
  of	
  x	
  is	
  ${x}")
You’ve	
  seen	
  this	
  before.
Express yourself
Friday, August 23, 13
puppetconf.com #puppetconf
$x	
  =	
  5
$y	
  =	
  3
notice("Five	
  by	
  three	
  is	
  ${$x	
  *	
  $y}")
Express yourself
Friday, August 23, 13
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
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
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
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
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
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
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
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
puppetconf.com #puppetconf
And at this point I was like
Friday, August 23, 13
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
puppetconf.com #puppetconf
So then I was like
Friday, August 23, 13
puppetconf.com #puppetconf
Friday, August 23, 13
puppetconf.com #puppetconf
yeah
Friday, August 23, 13
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
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
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
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
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
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
puppetconf.com #puppetconf
Anyway,what did I learn?
(In the larger sense,not in
the str2bool({t => ‘r’,u =>
‘e’}) sense.)
Friday, August 23, 13
puppetconf.com #puppetconf
Do science to it.
Friday, August 23, 13
puppetconf.com #puppetconf
Long-lived systems get
weird.
Friday, August 23, 13
puppetconf.com #puppetconf
Talk to the old-timers.
Friday, August 23, 13
puppetconf.com #puppetconf
WAT brings us together!
Friday, August 23, 13
puppetconf.com #puppetconf
(Pause here for general
theory of the social capital
of WAT in engineering
cultures.)
Friday, August 23, 13
puppetconf.com #puppetconf
And venting about WAT
can keep your morale up.
Because c’mon.
That’s pretty funny.
Friday, August 23, 13
puppetconf.com #puppetconf
https://
github.com/
nfagerlund/
evil-made-
manifest
(photo via http://
taterpie.tumblr.com/
post/56826040138/
thats-an-awesome-
shot)
Friday, August 23, 13
Thank You
Nick Fagerlund
Technical Writer | Puppet Labs
@nfagerlund
Collaborate. Automate. Ship.
Friday, August 23, 13
Follow us on Twitter @puppetlabs
youtube.com/puppetlabsinc
slideshare.net/puppetlabs
Collaborate. Automate. Ship.
Friday, August 23, 13

DSL Quest: A WAT Safari - PuppetConf 2013

  • 1.
    Nick’s DSL Quest: WATSafari Nick Fagerlund Technical Writer | Puppet Labs @nfagerlund Friday, August 23, 13
  • 2.
    puppetconf.com #puppetconf So okay,thereI was. Friday, August 23, 13
  • 3.
    puppetconf.com #puppetconf When Ifirst got here,we had this “language tutorial.” Friday, August 23, 13
  • 4.
    puppetconf.com #puppetconf It wasa bit of a mess. (“Additional language features…?”) Friday, August 23, 13
  • 5.
    puppetconf.com #puppetconf The Puppetlanguage accreted over time. Friday, August 23, 13
  • 6.
    puppetconf.com #puppetconf (And sodid the docs.) Friday, August 23, 13
  • 7.
    puppetconf.com #puppetconf So Ihad a good/bad idea. Friday, August 23, 13
  • 8.
    puppetconf.com #puppetconf Here’s whatI found. Friday, August 23, 13
  • 9.
    puppetconf.com #puppetconf $subj  =  {t  =>  'r',  u  =>  'e'} notice(str2bool("$subj")) T to the R Friday, August 23, 13
  • 10.
    puppetconf.com #puppetconf $subj  =  {t  =>  'r',  u  =>  'e'} notice(str2bool("$subj")) true T to the R Friday, August 23, 13
  • 11.
  • 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
  • 17.
  • 18.
  • 19.
    puppetconf.com #puppetconf class  class  {    notify  {'hey  it  worked':} } include  class Results Classy 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
  • 21.
    puppetconf.com #puppetconf class  class  {    notify  {'hey  it  worked':} } include  "class" 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
  • 25.
    puppetconf.com #puppetconf (This isstill in Puppet 3.2.) (photo via http:// weheartit.com/entry/ 68358166) Friday, August 23, 13
  • 26.
    puppetconf.com #puppetconf [  Notify['first'],  Notify['second']  ] It’s  an  array  of  resource  references,  right? Have you seen this syntax? Friday, August 23, 13
  • 27.
    puppetconf.com #puppetconf Notify[  'first',  'second'  ] ??? How about this one? Friday, August 23, 13
  • 28.
    puppetconf.com #puppetconf Notify[  ['first',  'second']  ] (Okay,  it  ends  up  being  the  same  as  the  last  one  for  some   reason.) How about this one? 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
  • 31.
    puppetconf.com #puppetconf So,these aretwo completely different syntaxes. (I named the non-array one “multi- references.) 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
  • 35.
  • 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
  • 38.
    puppetconf.com #puppetconf (Use thestr2bool() function from puppetlabs/stdlib) Friday, August 23, 13
  • 39.
  • 40.
    puppetconf.com #puppetconf Code Results What IStruth,anyway? Friday, August 23, 13
  • 41.
    puppetconf.com #puppetconf $x  =  5 $y  =  3 notice("Value  of  x  is  ${x}") You’ve  seen  this  before. Express yourself Friday, August 23, 13
  • 42.
    puppetconf.com #puppetconf $x  =  5 $y  =  3 notice("Five  by  three  is  ${$x  *  $y}") Express yourself 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
  • 51.
    puppetconf.com #puppetconf And atthis point I was like Friday, August 23, 13
  • 52.
    puppetconf.com #puppetconf (It turnsout 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
  • 53.
    puppetconf.com #puppetconf So thenI was like Friday, August 23, 13
  • 54.
  • 55.
  • 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
  • 62.
    puppetconf.com #puppetconf Anyway,what didI learn? (In the larger sense,not in the str2bool({t => ‘r’,u => ‘e’}) sense.) Friday, August 23, 13
  • 63.
    puppetconf.com #puppetconf Do scienceto it. Friday, August 23, 13
  • 64.
    puppetconf.com #puppetconf Long-lived systemsget weird. Friday, August 23, 13
  • 65.
    puppetconf.com #puppetconf Talk tothe old-timers. Friday, August 23, 13
  • 66.
    puppetconf.com #puppetconf WAT bringsus together! Friday, August 23, 13
  • 67.
    puppetconf.com #puppetconf (Pause herefor general theory of the social capital of WAT in engineering cultures.) Friday, August 23, 13
  • 68.
    puppetconf.com #puppetconf And ventingabout WAT can keep your morale up. Because c’mon. That’s pretty funny. Friday, August 23, 13
  • 69.
    puppetconf.com #puppetconf https:// github.com/ nfagerlund/ evil-made- manifest (photo viahttp:// taterpie.tumblr.com/ post/56826040138/ thats-an-awesome- shot) Friday, August 23, 13
  • 70.
    Thank You Nick Fagerlund TechnicalWriter | Puppet Labs @nfagerlund Collaborate. Automate. Ship. Friday, August 23, 13
  • 71.
    Follow us onTwitter @puppetlabs youtube.com/puppetlabsinc slideshare.net/puppetlabs Collaborate. Automate. Ship. Friday, August 23, 13