# Instead of
some data <%= scope.hiera_lookup('::myclass::myvalue') %>
# Use
some data <%= lookup('::myclass::myvalue') %>
# Or better
some data <%= @myvalue %>
# And then on the .pp file that uses this template:
#
# $myvar = hiera('::myclass::myvalue')
# $content = template('mymodule/mytemplate.erb')
#
# Given this class:
----- mymodule/myclass.pp
class mymodule::myclass {
$anothervar = 'something'
notify { template('anothermodule/anothertemplate.erb')
}
-----
---- anothermodule/templates/anothertemplate.erb
This is the template from anothermodule, <%= @anothervar %>
----
# with puppet3
----
This is the template from anothermodule, something
----
# BUT!!! in puppet4
----
This is the template from anothermodule,
----
No dynamic namespaces anymore!
CERN ONLY: Careful with teigi secrets, they might end up being empty
# Instead of passing the template name
teigi::secret::sub_file{"/file_with_secrets":
template => 'mymod/template.erb',
teigi_keys => $tbags,
owner => $user,
group => $group,
mode => '0640',
}
# use the new 'content' parameter
teigi::secret::sub_file{"/file_with_secrets":
content => template('mymod/template.erb'),
teigi_keys => $tbags,
owner => $user,
group => $group,
mode => '0640',
}
# This same snippet
$port = ''
if $port {
notify {"Got port ${port}": }
} else {
notify {'No port passed!': }
}
# On puppet 3
[test@0fc2514c4e5d code]$ bundle exec puppet --version
3.8.7
[test@0fc2514c4e5d code]$ bundle exec puppet apply test.pp
Notice: Compiled catalog for 0fc2514c4e5d.home in environment production in 0.01 seconds
Notice: No port passed!
Notice: /Stage[main]/Main/Notify[No port passed!]/message: defined 'message' as 'No port passed!'
Notice: Finished catalog run in 0.01 seconds
# But on puppet 4
[test@0815d666e8ff code]$ bundle exec puppet --version
4.8.2
[test@0815d666e8ff code]$ bundle exec puppet apply test.pp
Notice: Compiled catalog for 0815d666e8ff.home in environment production in 0.10 seconds
Notice: Got port
Notice: /Stage[main]/Main/Notify[Got port ]/message: defined 'message' as 'Got port '
Notice: Applied catalog in 0.02 seconds
Basic (core) data types:
String
Integer
Float
Numeric
Boolean
Array
Hash
Regexp
Undef
Default
# Use them everywhere!
class dummy(
String name,
Integer age,
Array[Integer] grades,
Hash extra_params,
) {
...
}
# A combo with Default and bool-string handling:
$use_feature = $feature ? {
Boolean => $feature,
String => str2bool($feature),
Default => true,
}
Flexible data types:
Variant
Pattern
Optional
NotUndef
Enum
Tuple
Struct
class myclass(
# Might be string or integer
Variant[String, Integer] port = 12,
# Match any sting starting with lowercase letter
Pattern[/\A[a-z].*/] lowercased = 'aOEU',
# Might be undef or string
Optional[String] might_be_undef = undef,
# Might be anything but undef
NotUndef not_undef = 'something',
# Matches either string 'one' or 'two'
Enum['one', 'two'] how_many = 'one',
# Specify one by one the types of each element
Tuple[String, String, Integer] triplet = ['one', 'two', 3],
# Definition of a hash structure
Struct[{
name => String,
home => String,
uid => Integer,
}] user,
)
Parent data types:
Scalar
Collection
Data
Catalogentry
Type
Any
Unusual data types:
# Integer ranges
Integer[1,1024] $listen_port = 22
# Enums
Enum['*','::1','127.0.0.1'] $listen_ip = '*',
# Patterns
Pattern[/^\/.*/] $home
# Complex hashmaps
Hash[String, Struct[{ uid => Integer, home => Pattern[/^\/.*/]}]] $hash
# That matches for example:
# {
# uid => 0,
# home => '/root',
# }
#
# but not
# {
# uid => 'root',
# home => 'my/relative/path',
# }
EPP == Embedded puppet templates
Some diffs with erb:
------ example.epp file --------
<% | String $text, $Array $array, Boolean $bool |>
<% if $string -%>
Text from variable: <%= $string %>
<% end -%>
<% if $array -%>
<% $array.each |$element| { -%>
Array item: <%= $element %>
<% } -%>
<% end -%>
<% if $bool -%>
Bool value is true
<% end -%>
---------------------------------
------- .pp code using it -------
file { '/dummy':
ensure => file,
content => epp(
'test/example.epp',
{
text => 'foo',
array => ['one', 'two'],
bool => false
}),
}
---------------------------------
Nicer strings!
class my_example {
$content = @("EOF")
This is a very long string
with some variables on it, for example:
-> here is the fqdn ${::fqdn)
You will also notice that the indentation
in front of the string will be removed, that
can be avoided (if wanted), by not using the
pipe right before the end-of-file tag string.
| EOF
file { '/example':
ensure => file,
content => $content,
}
}
Finally loops!! (kinda)
$data = ["routers", "servers", "workstations"]
$data.each |$item| {
notify { $item:
message => $item
}
}
# For the hash $data, return a hash containing all
# values of keys that end with "berry"
$data = {
"orange" => 0,
"blueberry" => 1,
"raspberry" => 2
}
$filtered_data = $data.filter |$items| {
$items[0] =~ /berry$/
}
# $filtered_data = {blueberry => 1, raspberry => 2}
$data = [1,2,3]
$transformed_data = $data.map |$items| { $items * 10 }
$sum = $data.reduce |$memo, $value| { $memo + $value }
slice([1,2,3,4,5], 2) # produces [[1,2], [3,4], [5]]
*CERN specific
With docker
Dockerfile:
# Puppet 3 build:
# docker build --build-arg puppet_version=3.0 Dockerfile
#
# Puppet 4 build:
# docker build --build-arg puppet_version=4.8.0 Dockerfile
#
# Latest Puppet 4 build:
# docker build --build-arg puppet_version=4.0 Dockerfile
#
FROM gitlab-registry.cern.ch/ai/it-puppet-module-ci_images:cc7-puppet-ci-master
ARG puppet_version=3.0
WORKDIR /code/code
ENV BUNDLE_GEMFILE=../ci/Gemfile
ENV PUPPET_VERSION="~> ${puppet_version}"
ENV LANG=en_US.UTF-8
# Run tests
RUN useradd test
USER test
ENTRYPOINT rm -f ../ci/Gemfile.lock \
&& bundle install --local --without system_tests development \
&& bundle exec rake --rakefile ../ci/Rakefile test
With docker
docker-compose.yml:
version: '2'
# To run the tests run the service for the puppet version you want:
# docker-compose run --rm puppet3
#
# If not already built, it will build the images for you.
services:
puppet3:
build:
context: .
dockerfile: Dockerfile
args:
puppet_version: 3.0
container_name: puppet3_ci
volumes:
- "$PWD:/code"
With docker
docker-compose.yml (continued):
puppet4:
extends: puppet3
build:
args:
puppet_version: 4.8.0
container_name: puppet4_ci
puppet4_latest:
extends: puppet3
build:
args:
puppet_version: 4.0
container_name: puppet4_latest_ci
With docker
$ docker-compose run puppet3
$ docker-compose run puppet4
$ docker-compose run puppet4_latest
* CERN specific
Maintained by CERN config management team
Automatic updates (as merge requests)