8. Why
• Started to backsource our hosting.
• Need for automation to grow quickly.
• Single point of administration.
• Servers bootstrapped through FAI.
• Puppet does the rest.
Friday, February 1, 13
9. Early days
• Puppet: 0.25 - 2.6.
• Puppet changing at a rapid pace.
• Our manifests growing exponentially.
• Manifests, modules, nodes, argh.
Friday, February 1, 13
10. Growing
• Limited knowledge on creating Puppet
modules.
• Sparse information on how to create
good modules.
• Difficult to separate logic from data.
• Lots and lots of nagios hosts, services
and checks.
Friday, February 1, 13
12. Fixing
• Admit you have a problem...
• Take time to fix it!
• Introduce Hiera for data.
• Split modules in small, simple, classes.
• Tests, tests, tests!
Friday, February 1, 13
21. Data
• Not possible to keep
everything in one place
• Duplication of data within a
single source
Friday, February 1, 13
22. Community
• Help people first...
• Then tell them they’re doing it
wrong.
Friday, February 1, 13
23. Community
• Help people first...
• Then tell them they’re doing it
wrong.
• 2.7.0 is the first version of
Puppet to support Ruby 1.9.
Friday, February 1, 13
32. Testing yolo
class
yolo
{
notic
{
'yolo':
}
}
require
'spec_helper'
describe
'yolo'
do
it
"should
build"
do
should
contain_class('yolo')
end
end
Friday, February 1, 13
33. Testing yolo
rake
spec
Failures:
1)
yolo
should
build
Failure/Error:
should
contain_class('yolo')
Puppet::Error:
Puppet::Parser::AST::Resource
failed
with
error
ArgumentError:
Invalid
resource
type
notic
at
yolo/manifests/init.pp:40
#
./spec/classes/yolo_spec.rb:5
Finished
in
0.0809
seconds
1
example,
1
failure
Friday, February 1, 13
34. Fail fast
class
yolo
(
$param
=
false,
){
validate_string($param)
}
require
'spec_helper'
describe
'yolo'
do
it
"should
build"
do
should
contain_class('yolo')
end
end
Friday, February 1, 13
35. Fail fast
rake
spec
Failures:
1)
yolo
should
build
Failure/Error:
should
contain_class('yolo')
Puppet::Error:
false
is
not
a
string.
It
looks
to
be
a
FalseClass
at
yolo/manifests/init.pp:40
#
./spec/classes/yolo_spec.rb:5
Finished
in
0.0809
seconds
1
example,
1
failure
Friday, February 1, 13
36. Fail more
class
yolo
(
$param=false,
){
validate_string($param)
if
empty($param){
fail(‘Dude,
wth,
empty?!’)
}
}
require
'spec_helper'
describe
'yolo'
do
let
:params
do
{
:param
=>
''
}
end
[..]
end
Friday, February 1, 13
37. Fail more
rake
spec
Failures:
1)
yolo
should
build
Failure/Error:
should
contain_class('yolo')
Puppet::Error:
Dude,
wth,
empty?!
at
yolo/manifests/
init.pp:43
#
./spec/classes/yolo_spec.rb:5
Finished
in
0.0809
seconds
1
example,
1
failure
Friday, February 1, 13
38. Check your validation
require
'spec_helper'
describe
'yolo'
do
context
'with
invalid
$param
type'
do
let
:params
do
{
:param
=>
{}
}
end
it
"should
break
horribly"
do
expect
{
subject
}.to
raise_error(Puppet::Error,
/{}
is
not
a
string/)
end
end
end
Friday, February 1, 13
39. Check your validation
rake
spec
.
Finished
in
0.08736
seconds
1
example,
0
failures
Friday, February 1, 13
40. Check your facts
class
yolo(
$param
=
$yolo::params::lol
)
inherits
yolo::params
{
[do
stuff,
like
validation]
}
Friday, February 1, 13
41. Check your facts
class
yolo::params
{
case
$::osfamily
{
'Debian':
{
[set
some
really
fancy
variables]
}
default:
{
fail("$osfamily
${::osfamily}
is
not
supported
by
the
yolo
module.")
}
}
}
Friday, February 1, 13
42. Check your facts
describe
'on
unsupported'
do
let
:facts
do
{
:osfamily
=>
'Little
Red
Riding
Hood'
}
end
it
'should
fail'
do
expect
{
subject
}.to
raise_error(/
osfamily
Little
Red
Riding
Hood
is
not
supported/)
end
end
Friday, February 1, 13
43. Check your resources
class
yolo::configs
{
file
{
$f_yolo_default:
#
Template
uses
$interfaces
content
=>
template('yolo/default.erb'),
}
}
Friday, February 1, 13
44. Check your resources
describe
'yolo::configs'
do
let
:params
do
{
:f_yolo_default
=>
'/etc/default/yolo',}
end
it
do
should
contain_file('/etc/default
yolo').with_content(/CATS="lol"/)
end
end
Friday, February 1, 13
45. Matchers
• For every resource: contain_resource()
• For every attribute: with_attr(‘value’)
• Or: with({:attr1
=>
‘value1’,
:attr2
=>
‘value2’})
• Check the content:
with_content(regex)
• include_class()
Friday, February 1, 13
46. Helpers
• let
:params
do
{
:param
=>
{}
}
end
• let
:facts
do
{
:osfamily
=>
‘’
}
end
• let
:pre_condition
do
'include
class::we::need'
end
Friday, February 1, 13