Transcript
Page 1: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Page 2: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Loops and Unicorns Future of the Puppet Language Henrik Lindberg Consulting Engineer | Puppet Labs @hel

Page 3: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  New parser •  New Language Features •  New approach – Opt in to New/Experimental Features – Maintaining Backwards Compatibility

Introduction

Page 4: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

New Parser The future is already here…

Page 5: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Rewritten from the ground up •  Removes quirky grammar constraints •  Improves error messages •  Enabler for: – opt-in to new and experimental features – backwards compatibility

•  Use on command line, or in settings

New Parser

puppet apply –-parser future ...

Page 6: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

De-Quirk

"This is a random number: ${fqdn_rand()}"

join([1,2,3])

$a = 0x0EH $b = 0778

Interpolation and functions work: Literal Array / Hash as argument in calls works: Numbers must now be valid:

Page 7: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Array & Hash

$a = [1,2,3] $b = [4,5,6] $c = $a + $b

Concatenate Arrays: Append to Array: Merge Hash:

$d = $a << 4

$a = {name => 'mary'} $b = {has => 'a little lamb'} $c = $a + $b

Page 8: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Misc

unless $something { . . .} else { . . . }

Unless Else: Assignment is an expression: Expression separator ';' :

$a = $b = 10 fqdn_rand($seed = 30)

$a = $x[1][1] $a = $x[1];[1]

Page 9: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Error Reporting

Error: Could not parse for environment production: Syntax error at 'node' at line 1 on node kermit.example.com

puppet apply -e '$a = node "a+b" { }' Then: Now:

Error: Invalid use of expression. A Node Definition does not produce a value at line 1:6 Error: The hostname 'a+b' contains illegal characters (only letters, digits, '_', '-', and '.' are allowed) at line 1:11 Error: Classes, definitions, and nodes may only appear at toplevel or inside other classes at line 1:6 Error: Could not parse for environment production: Found 3 errors. Giving up on node kermit.example.com

Page 10: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

New Approach

Page 11: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Forgiving Grammar •  Validation is separate – Can validate a particular language version – Language version != Puppet version

•  Evaluation is separate – Can evaluate a particular language version way – Language version != Puppet version

Separation of Language Concerns

Page 12: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

New Language Features

Page 13: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Page 14: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Page 15: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Page 16: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Page 17: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Iteration & Lambdas •  Puppet Bindings •  Heredoc support •  Puppet Templates

New Language Features

Page 18: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Iteration & Lambdas

Page 19: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Concepts

each($foo) |$x| { notice $x }

The lambda: Inline call:

$foo.each |$x| { notice $x } each($foo) |$x| { notice $x }

Page 20: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  each •  select – reject •  collect •  reduce •  slice

Custom functions can take a lambda!

Iterating Functions

Page 21: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Each - Array

$a = ['a', 'b', 'c'] $a.each |$value| { notice $value }

Iterating over an array: Produces:

Notice: Scope(Class[main]): a Notice: Scope(Class[main]): b Notice: Scope(Class[main]): c

Page 22: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Each – Array (with index)

$a = ['a', 'b', 'c'] $a.each |$index, $value| { notice "$index = $value" }

Iterating over an array – with index: Produces:

Notice: Scope(Class[main]): 0 = a Notice: Scope(Class[main]): 1 = b Notice: Scope(Class[main]): 2 = c

Page 23: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Each - Hash

$a = {a => 10, b => 20, c => 30} $a.each |$key, $value| { notice "$key = $value" }

Iterating over a hash – with key and value: Produces:

Notice: Scope(Class[main]): a = 10 Notice: Scope(Class[main]): b = 20 Notice: Scope(Class[main]): c = 30

Page 24: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Each – Hash (elements)

$a = {a => 10, b => 20, c => 30} $a.each |$elem| { notice "${elem[0]} = ${elem[1]}" }

Iterating over a hash elements: Produces:

Notice: Scope(Class[main]): a = 10 Notice: Scope(Class[main]): b = 20 Notice: Scope(Class[main]): c = 30

Page 25: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Select / Reject

$a = [1, 2, 3] notice $a.select |$value| { $v == 2 } notice $a.reject |$value| { $v == 2 }

Select and Reject elements: Produces:

Notice: Scope(Class[main]): 2 Notice: Scope(Class[main]): 1 3

Page 26: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Collect

$a = [1, 2, 3] notice $a.collect |$value| { $v * 10 }

Transform each element with collect: Produces:

Notice: Scope(Class[main]): 10 20 30

Page 27: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Reduce

$a = [1, 2, 3] notice $a.reduce |$memo, $value| { $memo + $value }

Reduce all elements into one: Produces:

Notice: Scope(Class[main]): 6

Page 28: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Examples

$usernames.each |$x| { file { "/home/$x/.somerc": owner => $x } }

Set ownership of some "rc-file" for each user: Setting 'owner' and 'mode' from a Hash:

$users_with_mode = ['fred' => 0666, 'mary' => 0777 ] $users_with_mode.each |$user, $mode| { file {"/home/$user/.somerc": owner => $user, mode => $mode } }

Page 29: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Examples

$a.select |$x| { $x =~ /com$/ }.each |$x| { file { "/somewhere/$x": owner => $x } }

Filter and create resources: Include classes based on array of roles:

$roles.each |$x| { include "role_$x" }

Page 30: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Custom Function (Ruby)

pp_block = args[-1]

Lambda always last argument: Was it given? Call it:

pp_block.is_a? Puppet::Parser::AST::Lambda

# in a custom function, self is scope) pp_block.call(self, 'hello', 'world')

Page 31: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  http://links.puppetlabs.com/arm2-iteration •  http://links.puppetlabs.com/arm2-examples

ARM 2 - Iteration

Page 32: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Heredoc

Not yet on master branch https://github.com/puppetlabs/puppet/pull/1659

Page 33: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Heredoc - Syntax

@( ["]<endtag>["] [:<syntax>] [/<escapes>] ) <text> [|][-] <endtag>

ENDS-­‐HERE  anything  not  in  <text>    "ENDS-­‐HERE"  with  interpola2on  

:json  syntax  check  result  

/tsrn$L    turns  on  escape  /      turns  on  all  

|  set  le7  margin  

-­‐  trim  trailing  

t  tab  s  space  r  return  n  new-­‐line  $  $  L  <end  of  line>  

Page 34: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Heredoc – example Example:

#.........1.........2.........3.........4.........5.... $a = @(END) This is indented 2 spaces in the source, but produces a result flush left with the initial 'T' This line is thus indented 2 spaces. | END

Page 35: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Heredoc – example multiple on same line:

#.........1.........2.........3.........4.........5.... foo(@(FIRST), @(SECOND)) This is the text for the first heredoc FIRST This is the text for the second SECOND

Page 36: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

For more examples and details •  http://links.puppetlabs.com/arm4-heredoc

ARM-4 Heredoc

Page 37: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Puppet Templates

Not yet on master branch https://github.com/puppetlabs/puppet/pull/1660

Page 38: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Embedded Puppet (EPP) - like ERB •  Same tags

§  <%, <%=, <%-, <%%, <%# § %>, -%>

•  Expressions are Puppet DSL •  Parameterized •  .epp file extension (by convention)

Puppet Templates

Page 39: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Use by calling epptemplate(<name> [,<params_hash>]) inline_epptemplate(<text>[,<params_hash>])

Puppet Templates

$x = 'human' inline_epptemplate('This is not the <%= $x %> you are looking for.', { 'x' => 'droid'}) # => 'This is not the droid you are looking for.'

Page 40: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Parameterized – declare parameters – set default values – parameter without value and no default = error

Puppet Templates

<%- ($x = 'human') -%> This is not the <%= $x %> you are looking for.

Page 41: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

For more examples and details •  http://links.puppetlabs.com/arm3-

puppet_templates

ARM-3 Puppet Templates

Page 42: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Puppet Bindings / Data in Modules

Page 43: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  More powerful data bindings •  For both Data, and Puppet Extensions •  Composes Hiera2 data in modules and

environment + Hiera1 •  Bindings in Ruby •  Opt in on command line or in settings

Puppet Binder

puppet apply --binder puppet apply –-parser future ...

Page 44: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Default: – All hiera-2 data (in default location) and all

(default) ruby bindings from all modules on module path composed

– Site level hiera-2 data and ruby bindings override contributions from modules.

•  Customize –  include alternatives, exclude bindings – add / reorganize overriding "layers"

Configuration

Page 45: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

•  Composable •  Interpolation using Puppet DSL expressions •  Changed hiera.yaml syntax (for version 2)

Hiera 2

Page 46: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

Minimal opt-in (in a module)

--- version: 2

hiera.yaml: data/common.yaml: data/${osfamily}.yaml:

--- myclass::myparam: '1.2.3'

--- myclass::myparam: '2.4.6'

Page 47: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

puppetconf.com #puppetconf

For more examples and details •  http://links.puppetlabs.com/arm8-

puppet_bindings •  http://links.puppetlabs.com/arm9-

data_in_modules

ARM-8 & 9

Page 48: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013
Page 49: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Thank You Henrik Lindberg Consulting Engineer | Puppet Labs @hel

Collaborate. Automate. Ship.

Page 50: Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013

Follow us on Twitter @puppetlabs youtube.com/puppetlabsinc slideshare.net/puppetlabs

Collaborate. Automate. Ship.


Top Related