dsl quest: a wat safari - puppetconf 2013

71
Nick’s DSL Quest: WAT Safari Nick Fagerlund Technical Writer | Puppet Labs @nfagerlund Friday, August 23, 13

Upload: puppet-labs

Post on 07-Nov-2014

626 views

Category:

Technology


1 download

DESCRIPTION

"DSL Quest: A WAT Safari" by Nick Fagerlund, Technical Writer, Puppet Labs. Presentation Overview: You are standing in an open field, west of a programming language with no specification. ENTER COMMAND. In mid-2012, docs.puppetlabs.com published a completely rewritten reference to the Puppet domain-specific language (DSL). This session is partly the story of how Nick built that, but it's mostly a safari of the weird crap he found along the way, a look at the personality of an undocumented system, a few tips for using Puppet as a calculator, some mission-creep schadenfreude, and maybe the faintest outline of a map for anyone trapped in a maze of twisty passages. Speaker Bio: Nick Fagerlund was the very first dedicated technical writer at Puppet Labs. Like any responsible pet owner, Puppet Labs has since provided him with companions. Unlike a responsible pet owner, Puppet Labs has fed him after midnight and occasionally splashed water on him. Nick writes (and re-writes) at http://docs.puppetlabs.com, focusing on platform-level components like the Puppet language. He specializes in breaking things and then explaining how they broke. His business card says "weird bugs."

TRANSCRIPT

Page 1: DSL Quest: A WAT Safari - PuppetConf 2013

Nick’s DSL Quest:WAT SafariNick FagerlundTechnical Writer | Puppet Labs @nfagerlund

Friday, August 23, 13

Page 2: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

So okay, there I was.

Friday, August 23, 13

Page 3: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

When I first got here, we had this “language

tutorial.”

Friday, August 23, 13

Page 4: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

It was a bit of a mess.(“Additional language features…?”)

Friday, August 23, 13

Page 5: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

The Puppet language accreted over time.

Friday, August 23, 13

Page 6: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

(And so did the docs.)

Friday, August 23, 13

Page 7: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

So I had a good/bad idea.

Friday, August 23, 13

Page 8: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Here’s what I found.

Friday, August 23, 13

Page 9: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

$subj  =  {t  =>  'r',  u  =>  'e'}

notice(str2bool("$subj"))

T to the R

Friday, August 23, 13

Page 10: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

$subj  =  {t  =>  'r',  u  =>  'e'}

notice(str2bool("$subj"))

true

T to the R

Friday, August 23, 13

Page 11: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Friday, August 23, 13

Page 12: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 13: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Notify  <|  tag  ==  'one'  |>

Notice:  Compiled  catalog  for  magpie.lan  in  environment  production  in  0.11  secondsNotice:  one  tagNotice:  /Stage[main]//Notify[one  tag]/message:  defined  'message'  as  'one  tag'Notice:  three  tagsNotice:  /Stage[main]//Notify[three  tags]/message:  defined  'message'  as  'three  tags'Notice:  two  tagsNotice:  /Stage[main]//Notify[two  tags]/message:  defined  'message'  as  'two  tags'

Let’s talk about collectors

Friday, August 23, 13

Page 14: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 15: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Notify  <|  tag  ==  ['one',  'two']  |>

Notice:  Compiled  catalog  for  magpie.lan  in  environment  production  in  0.09  secondsNotice:  one  tagNotice:  /Stage[main]//Notify[one  tag]/message:  defined  'message'  as  'one  tag'Notice:  three  tagsNotice:  /Stage[main]//Notify[three  tags]/message:  defined  'message'  as  'three  tags'Notice:  two  tagsNotice:  /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

Page 16: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Notify  <|  tag  !=  ['one',  'two']  |>

Notice:  Compiled  catalog  for  magpie.lan  in  environment  production  in  0.09  secondsNotice:  three  tagsNotice:  /Stage[main]//Notify[three  tags]/message:  defined  'message'  as  'three  tags'Notice:  two  tagsNotice:  /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

Page 17: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

CONCLUSION:“==” != “==”

Friday, August 23, 13

Page 18: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Friday, August 23, 13

Page 19: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

class  class  {    notify  {'hey  it  worked':}}

include  class

Results

Classy

Friday, August 23, 13

Page 20: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 21: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

class  class  {    notify  {'hey  it  worked':}}

include  "class"

Classy

Friday, August 23, 13

Page 22: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

class  class  {    notify  {'hey  it  worked':}}

include  "class"

Notice:  Compiled  catalog  for  magpie.lan  in  environment  production  in  0.09  secondsNotice:  hey  it  workedNotice:  /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

Page 23: DSL Quest: A WAT Safari - PuppetConf 2013

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  whoanotice($otherparentvar)  #  This  one  doesn't  work  though,  because  it  attaches  the  NAMESPACE,  not  the  scope.

Search???

Friday, August 23, 13

Page 24: DSL Quest: A WAT Safari - PuppetConf 2013

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  whoanotice($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

Page 25: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

(This is still in Puppet 3.2.)

(photo via http://weheartit.com/entry/

68358166)

Friday, August 23, 13

Page 26: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

[  Notify['first'],  Notify['second']  ]

It’s  an  array  of  resource  references,  right?

Have you seen this syntax?

Friday, August 23, 13

Page 27: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Notify[  'first',  'second'  ]

???

How about this one?

Friday, August 23, 13

Page 28: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 29: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

#  OKrequire  =>  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

Page 30: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

#  OKNotify['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

Page 31: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

So, these are two completely different

syntaxes. (I named the non-array one “multi-

references.)

Friday, August 23, 13

Page 32: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 33: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 34: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

#  Is  the  ==  operator  case-­‐sensitive?  NOnotice(  'eat'  ==  'EAt'  )

#  Is  the  'in'  operator  case-­‐sensitive?  YESnotice(  'eat'  in  'EAten'  )

Notice:  Scope(Class[main]):  trueNotice:  Scope(Class[main]):  false

Case sensitivity training

Friday, August 23, 13

Page 35: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

ANYWAY

Friday, August 23, 13

Page 36: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

#  The  $is_virtual  fact  is  false  on  this  machineif  $is_virtual  {    notice("Guess  this  is  a  virtual  machine!")}

Falseness is truth

Friday, August 23, 13

Page 37: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

#  The  $is_virtual  fact  is  false  on  this  machineif  $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

Page 38: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

(Use the str2bool() function from

puppetlabs/stdlib)

Friday, August 23, 13

Page 39: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

This, of course, escalated quickly.

Friday, August 23, 13

Page 40: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Code

Results

What IS truth, anyway?

Friday, August 23, 13

Page 41: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

$x  =  5$y  =  3notice("Value  of  x  is  ${x}")

You’ve  seen  this  before.

Express yourself

Friday, August 23, 13

Page 42: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

$x  =  5$y  =  3notice("Five  by  three  is  ${$x  *  $y}")

Express yourself

Friday, August 23, 13

Page 43: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

$x  =  5$y  =  3notice("Five  by  three  is  ${$x  *  $y}")

Notice:  Scope(Class[main]):  Five  by  three  is  15

Express yourself

Friday, August 23, 13

Page 44: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 45: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 46: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 47: DSL Quest: A WAT Safari - PuppetConf 2013

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  yeahNotice:  Scope(Class[main]):  Singular  sigil,  but  with  wacky  spacing:  5  so  yeah

Express yourself

Friday, August 23, 13

Page 48: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 49: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 50: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 51: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

And at this point I was like

Friday, August 23, 13

Page 52: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 53: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

So then I was like

Friday, August 23, 13

Page 54: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Friday, August 23, 13

Page 55: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

yeah

Friday, August 23, 13

Page 56: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 57: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 58: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 59: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 60: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 61: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 62: DSL Quest: A WAT Safari - PuppetConf 2013

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

Page 63: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Do science to it.

Friday, August 23, 13

Page 64: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Long-lived systems get weird.

Friday, August 23, 13

Page 65: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

Talk to the old-timers.

Friday, August 23, 13

Page 66: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

WAT brings us together!

Friday, August 23, 13

Page 67: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

(Pause here for general theory of the social capital

of WAT in engineering cultures.)

Friday, August 23, 13

Page 68: DSL Quest: A WAT Safari - PuppetConf 2013

puppetconf.com #puppetconf

And venting about WAT can keep your morale up.

Because c’mon.

That’s pretty funny.

Friday, August 23, 13

Page 70: DSL Quest: A WAT Safari - PuppetConf 2013

Thank YouNick FagerlundTechnical Writer | Puppet Labs @nfagerlund

Collaborate. Automate. Ship.

Friday, August 23, 13

Page 71: DSL Quest: A WAT Safari - PuppetConf 2013

Follow us on Twitter @puppetlabs

youtube.com/puppetlabsinc

slideshare.net/puppetlabs

Collaborate. Automate. Ship.

Friday, August 23, 13