Resources & the RAL

The resource abstraction layer.

Intermediate12 min · lesson 2 of 12

The resource is Puppet’s atom: a declaration of one piece of state, with a type, a title, and attributes. package, file, service, user, cron, exec — each models something on the system. The syntax reads like the model it is: type { title: attribute => value }. A handful of resource types covers most configuration, and you compose them into the full description of a machine.

init.pp
package { 'nginx':
ensure => installed,
}
file { '/etc/nginx/nginx.conf':
ensure => file,
content => template('nginx/nginx.conf.epp'),
notify => Service['nginx'], # reload service if this changes
}
service { 'nginx':
ensure => running,
enable => true,
}

The Resource Abstraction Layer

Behind each resource type sits the RAL — the Resource Abstraction Layer — which maps your declaration to a provider appropriate for the node. package { ‘nginx’: } installs via apt on Debian and yum/dnf on RHEL because the RAL selects the right provider from the node’s facts. This is what makes one manifest portable across a heterogeneous fleet, and why you declare the abstract resource rather than the OS-specific command.

terminal
# inspect the live state of a resource type via the RAL
$ puppet resource package nginx
package { 'nginx':
ensure => '1.24.0-1',
}
$ puppet resource service nginx
service { 'nginx': ensure => 'running', enable => 'true' }
exec is the escape hatch — guard it
The exec resource runs an arbitrary command and, like Chef’s execute or Ansible’s shell, is not idempotent by itself — it runs every catalog apply unless you constrain it. Always add creates, onlyif, or unless so it fires only when needed, and prefer a real resource type first. Ungoverned exec is the top cause of non-idempotent, surprising Puppet runs.