Whirlwind Tour of Puppet 4

39
R.I.Pienaar Puppet Camp Morristown 2016 Whirlwind Tour of Puppet 4

Transcript of Whirlwind Tour of Puppet 4

R.I.Pienaar

Puppet Camp Morristown 2016

Whirlwind Tourof Puppet 4

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Who am I?

• Puppet user since 0.22.x

• Author Hiera, MCollective, facts.d, etc

• Blog at http://devco.net

• Tweets at @ripienaar

• Volcane on IRC

• Consultant for hire

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Puppet 4?

• Currently 4.5.2 and uses Semver.

• >10 releases and now ready for production

• Massive internal rewrite

• Formal language specification

• Many new and improved features

• New DSL, but backward(ish) compatible

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Language Types

class ntp ( $servers, $config_dir = undef, $ensure = “present” ) { validate_array($servers) validate_absolute_path($config_dir) if !([$ensure in [“present”, “absent”]) { fail(“not a valid value for ensure”) } }

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

class ntp ( Array[String] $servers, Optional[Pattern[/^\//]] $config_dir, Enum[“present”, “absent”] $ensure = “present” ) { # … }

Language Types

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

type Ntp::Server = Pattern[ /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/

]

Language Types

class ntp ( Array[Ntp::Server] $servers, Optional[Pattern[/^\//]] $config_dir, Enum[“present”, “absent”] $ensure = “present” ) { # … }

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$enable_real = $enable ? { Boolean => $enable, String => str2bool($enable), Numeric => num2bool($enable), default => fail('Illegal value for $enable parameter'), } if 5 =~ Integer[1,10] { notice("it's a number between 1 and 10") }

Language Types

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Hash[String, Struct[{ match => Optional[Enum["all", "any"]], rules => Array[ Struct[{ fact => Optional[Data], operator => Enum["==", "=~", ">", " =>", "<", "<=", "has_ip_network"], value => Data, invert => Optional[Boolean] }] ], data => Optional[Hash[Pattern[/\A[a-z0-9_][a-zA-Z0-9_]*\Z/], Data]], classes => Optional[Array[Pattern[/\A([a-z][a-z0-9_]*)?(::[a-z][a-z0-9_]*)*\Z/]]] }] ]

Language Types

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

type Classifier::Classification = Struct[{ match => Optional[Classifier::Matches], rules => Array[Classifier::Rule], data => Optional[Classifier::Data], classes => Optional[Array[Classifier::Classname]] }]

type Classifier::Classifications = Hash[ String, Classifier::Classification ]

Language Types

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$a={"a" => “b"} $b={"c" => “d"}

notice($a+$b)

Native Data Merges

Notice: Scope(Class[main]): {a => b, c => d}

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

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

notice(“sum: ${$a+$b}”) notice(“difference: ${$a-$b}”)

Native Data Merges

sum: [1, 2, 3, 1, 4, 5, 6] difference: [2, 3]

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

File { mode => “0600”, owner => “root”, group => “root” }

file{“/some/file”: source => “puppet:///some/file” }

include another_class

Resource Defaults

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

file { default: mode => “0600”, owner => “root”, group => “root”;

“/some/file”: source => “puppet:///some/file”;

“/some/other/file”: source => “puppet:///other/file”; }

include another_class

Resource Defaults

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

[“puppet”, “facter”].each |$file| { file{“/usr/bin/${file}”: ensure => “link”, target => “/opt/puppetlabs/bin/${file}” } }

Iteration

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$domains = [“example.com”, “example.net”]

$data = $domains.map |$domain| { { $domain => { “relay” => “mx.${domain}” } } }

Iteration

{ “example.com” => {“relay” => “mx.example.com”}, “example.net” => {“relay” => “mx.example.net”} }

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

{ "example.net": { "nexthop": "70.x.x.x", "spamdestination": "[email protected]", "spamthreshold": 1500, "enable_antispam": 1 },

“example.com": { "nexthop": "70.x.x.x", "spamdestination": "[email protected]", "spamthreshold": 1500, "enable_antispam": 1 }, }

Iteration

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

each($domain) |$name, $domain| { mail::domain{$name: * => $domain } }

Iteration

Bonus feature: splat operator!

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$defaults = { “spamthreshold” => 1500, “enable_antispam” => 1 }

each($domain) |$name, $domain| { mail::domain{$name: * => $defaults + $domain } }

Iteration

Merging in the defaults and the supplied

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$defaults = { “spamthreshold” => 1500, “enable_antispam” => 1 }

each($domain) |$name, $domain| { mail::domain{ default: * => $defaults;

$name: * => $domain; } }

Iteration

This is create_resources()

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

each($data) |$item| { notice($item) }

.syntax

$data.each |$item| { notice($item) }

Any function, including old ones

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

class myapp { include myapp::install include myapp::config include myapp::service

notify{“done!”: } }

Default Ordering

Recent Puppet 3 set ordering=manifest for same

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

% facter os { architecture => "x86_64", distro => { release => { full => "7.2.1511", major => "7", minor => "2" }, … }, family => "RedHat", hardware => "x86_64", name => “CentOS", … }

Facts Hash

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

class bob { notice($facts[“os”][“distro”][“release”]) }

Facts Hash

Notice I am not using $::facts ?

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

class bob { $facts = “bad things will happen” }

Facts Hash

Error while evaluating a '=' expression, Attempt to assign to a reserved variable name: 'facts'

It’s globally reserved along with a few others

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

:hierarchy: - "%{facts.fqdn}" - "location_%{facts.location}" - "country_%{facts.country}" - common

Facts Hash

Hiera 3 supports nested hashes too

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$ time facter facter 0.05s user 0.04s system 69% cpu 0.126 total

Facter 3

It’s written in C++ but supports old facts

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$ facter os.distro.release.major 7

$ facter networking.interfaces.lo.bindings.0.address 127.0.0.1

Facter 3

The ‘0’ is for digging into arrays

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

$ puppet apply -e ‘$a = 1;$b = 2;notice($a+$b)’

Improved Parser

You can use a “;” to separate statements

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Improved Parser

Functions can go more or less anywhere

notify{hiera(“something”): }

notice("rand: ${fqdn_rand(100)}”)

notice("rand: ${10 + fqdn_rand(100)}")

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Improved Parser

Functions can go more or less anywhere

$pointless = hiera_hash(“things”)

$thing = $pointless[“thing”]

$thing = hiera_hash(“things”)[“thing”]

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Native Functionsfunction classifier::has_interface_detail ( String $match, Enum["address",“network"] $what="address" ) { $interfaces = $facts[“networking”][“interfaces”] $ips = $interfaces.map |$iname, $interface| { ["bindings", "bindings6"].map |$bname| { $interface[$bname].map |$binding| { $binding[$what] } } }.flatten

$match in $ips }

c::has_interface_detail(“127.0.0.1”) c::has_interface_detail(“::1”) c::has_interface_detail(“127.0.0.0”, “network”)

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Native Functionsfunction classifier::fact_fetch ( String $keys ) { $keys.split(/\./).reduce($facts) |$memo, $key| { if $memo !~ Undef {$memo[$key] } } }

classifier::facts_fetch(“os.distro.release.major”)

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Native Functions

function my::create_resource( String $type, Hash[String, Hash] $instances, Hash $defaults = {} ) { $instances.each |$r_name, $r_properties| { Resource[$type] {$r_name: * => $defaults + $r_properties } } }

Thus a native DSL create_resources()

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Data in Modulesclass ntp ( Array[Ntp::Server] $servers, String $config_file ) {

}

# data/os/AIX.yaml ntp::config_file: /etc/ntpd.conf

# data/common.yaml ntp::config_file: /etc/ntp.conf ntp::servers: - 1.pool.ntp.org …

Replaces params.pp pattern

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Lookup Strategiesclass ntp ( Array[Ntp::Server] $servers, String $config_file ) { # … }

# data/common.yaml lookup_options: ntp::servers: merge: strategy: unique

Replaces hiera_array() and hiera_hash()

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

AIO Packages% rpm -qi puppet-agent … augeas 1.4.0 facter 3.1.8 hiera 3.2.0 marionette-collective 2.8.8 openssl 1.0.2h puppet 4.5.2 puppet-ca-bundle 1.0.7 ruby 2.1.9 ruby-augeas 0.5.0 ruby-selinux 2.0.94 ruby-shadow 2.3.3 ruby-stomp 1.3.3 rubygem-deep-merge 1.0.1 rubygem-hocon 0.9.3 rubygem-net-ssh 2.9.2 rubygem-semantic_puppet 0.1.2 …

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

AIO Packages

% ls -l /etc/puppetlabs /opt/puppetlabs /etc/puppetlabs: total 8 drwxr-xr-x. 6 root root 4096 Mar 23 21:51 code drwxr-xr-x. 4 root root 4096 Apr 15 10:25 mcollective drwxr-xr-x. 3 root root 75 Apr 15 10:25 puppet drwxr-xr-x 3 root root 20 Mar 23 21:37 pxp-agent

/opt/puppetlabs: total 0 drwxr-xr-x. 2 root root 54 Apr 15 10:25 bin drwxr-xr-x. 3 root root 20 Mar 23 21:37 facter drwxr-xr-x 3 root root 20 Mar 23 21:37 mcollective drwxr-xr-x. 9 root root 102 Apr 15 10:25 puppet drwxr-xr-x 4 root root 32 Mar 23 21:54 pxp-agent

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Resources• This talk in blog form http://srt.ly/jj

• Iterating in Puppet http://srt.ly/jk

• Data in Modules http://srt.ly/jg

• Lookup Strategies http://srt.ly/jl

• Resource Wrapper Pattern http://srt.ly/jm

• Params.pp in Puppet 4 http://srt.ly/jn

• The Lookup Function http://srt.ly/jo

• Type Aliases http://srt.ly/jp

• A module showing off modern Puppet http://srt.ly/jq

R.I.Pienaar | [email protected] | http://devco.net | @ripienaar

Questions?

twitter: @ripienaaremail: [email protected]: www.devco.net

github: ripienaarfreenode: Volcane

slack: ripienaar

http://devco.net/