On Github mkpeacock / puppet-lightning-talk
The different aspects of your server puppet can manage, are referred to as resources; there are many different types of resources, and for aspects where features don't exist, modules can often fill the gaps brilliantly. Some of the key resources we will look at include
resource_type { 'title': attribute => value, attribute => value }
user { 'michael': ensure => "present", # create user if not there gid => "wheel", # use this group password => "somehash" }To use a resource, you specify its type, provide a title, and a set of attribtues. The title is unique and allows other resources to refer to each other; typicall the title doubles as a specific attribute. For example, on an exec it refers to the command you are running, however you can use a more friendly string as the title, and override the command by specifying the command attribute.
You can set one resource to depend on another using the require attribute
user { 'michael': ensure => "present", # create user if not there gid => "wheel", # use this group password => "somehash", require => [Group['wheel'], Class['chump']] }
stage { 'first': before => Stage['main'], } class { 'chump-module': stage => first }Either requiring an Exec resource, or an Exec requiring an Exec, has never been reliable for me. Stages are one solution to this. They let you group chunks of your puppet code together, and have certain groups run before the other
service { "nginx": ensure => "running", require => Package["nginx"], subscribe => Service["php5-fpm"] }
Typically related, reusable resources, structured in a configurable way.
modules ---- mymodule ---- ---- manifests ---- ---- ---- init.pp ---- ---- ---- othermanifests.pp ---- ---- /files ---- ---- ---- some-file.txt ---- ---- /templates ---- ---- ---- some-template.erb
file { '/etc/nginx/sites-available/default': source => "puppet:///modules/nginx/config-file", owner => 'root', group => 'root', notify => Service['nginx'], require => Package['nginx'] }
class mysql { package { "mysql-server": ensure => present } package { "mysql-client": ensure => present } package { "libmysqlclient15-dev": ensure => present } }/modules/mysql/manifests/init.pp
import "mysql" include mysqlmanifests/site.ppWhy is this bad? It provides no options for configuration, also a MySQL module would let us do things with the database server, such as create and manage MySQL users.
class iptables ($file = 'iptables') { exec { 'load-rules': command => "/sbin/iptables -F && /sbin/iptables-restore < /etc/iptables.up.rules", require => File['/etc/iptables.up.rules'], refreshonly => true } file { '/etc/iptables.up.rules': source => "puppet:///modules/iptables/${file}", owner => 'root', group => 'root', notify => Exec['load-rules'] } file { '/etc/network/if-pre-up.d/iptables': source => 'puppet:///modules/iptables/up', owner => 'root', group => 'root', mode => 755 } } modules/iptables/manifests/init.pp
class { 'iptables': file => 'external-staging-rules' }manifests/site.pp
Puppet Forge is the online repository of existing Puppet modules; most are well documented, and are on GitHub so you can include them as a submodule for your Puppet project. Make sure you also include dependencies.
As with code components, existing modules are a mixed bag and a balancing act; some give you lots of flexibility, others don't - so check that they support your needs
There are typically two types of manifest files; ones within modules, of which init.pp is called automatically when the module is invoked, and the manifests which relate to a specific server, and specify the modules which should be used and how they should be used