In Puppet, both include
and require
are used to declare class relationships, but they establish fundamentally different dependency chains:
# Safe declaration (soft dependency)
class webserver {
include apache
}
# Strict declaration (enforced ordering)
class database {
require mysql
}
The require
keyword creates an immediate hard dependency that Puppet must resolve during catalog compilation. When two classes require each other:
class A {
require B
}
class B {
require A # This creates a loop
}
Whereas include
creates a soft dependency that allows the catalog to compile first, then establishes relationships during application:
class A {
include B # No immediate validation
}
class B {
include A # Safe reciprocal inclusion
}
Follow these guidelines for optimal class declarations:
- Use
include
for most class relationships (90% of cases) - Only use
require
when strict ordering is absolutely necessary - Combine with resource-level ordering (
before
,require
) when needed
# Preferred pattern
class base {
include networking
include security
package { 'essential-tools':
ensure => present,
before => Class['networking']
}
}
For complex dependencies, consider these more maintainable approaches:
# Class chaining
class{'apache': } -> class{'mysql': }
# Resource collectors
Class['apache'] -> Class['mysql']
# Hiera-based declaration
lookup('classes', Array[String], 'unique', []).include
When encountering dependency loops, use these Puppet commands:
puppet master --compile node_name --debug
puppet catalog find node_name --render-as json
In Puppet, both include
and require
are used to declare classes, but they handle dependencies in fundamentally different ways:
# include example - non-strict declaration
class webserver {
include apache
}
# require example - strict dependency
class database {
require mysql
}
The critical behavior difference appears when classes reference each other:
# This creates circular dependency (BAD)
class A {
require B
}
class B {
require A
}
# This works fine (GOOD)
class A {
include B
}
class B {
include A
}
Puppet's catalog builder processes declarations differently:
- include: Adds the class to catalog without immediate evaluation
- require: Forces immediate evaluation and creates hard dependency
# Preferred pattern for most cases
class application {
include prerequisites # Soft dependency
require configuration # Hard dependency when absolutely needed
}
# Good alternative using contain
class secure_app {
include firewall
contain firewall # Creates proper scope boundary
}
For complex scenarios, consider these approaches:
# Parameterized class pattern
class app_server(
Boolean $require_db = true
) {
if $require_db {
require database
} else {
include database
}
}
# Class inheritance alternative
class base {
include common_packages
}
class app inherits base {
# automatically includes common_packages
}