You can classify nodes using an external node classifier (ENC), which is a script or
application that tells Puppet which classes a node must have.
It can replace or work in concert with the node definitions in the main site manifest
(site.pp
).
Depending on the external data sources you use in your infrastructure, building an external node classifier can be a valuable way to extend Puppet.
External node classifiers
An external node classifier is an
executable that Puppet Server or puppet apply
can call; it doesn’t have to be written in
Ruby. Its only argument is the name of the node to be classified, and it returns a
YAML document describing the node.
Inside the ENC, you can reference any data source you want, including PuppetDB. From Puppet’s perspective, the ENC submits a node name and gets back a hash of information.
External node classifiers can co-exist with standard node definitions in site.pp
; the classes declared in each
source are merged together.
Merging classes from multiple sources
Every node always gets a node object
from the configured node terminus. The node object might be empty, or it might
contain classes, parameters, and an environment. The node terminus
setting, node_terminus
,
takes effect where the catalog is compiled, on Puppet Server when using an agent-master configuration, and on the node itself when using
puppet apply
. The default node
terminus is plain
, which returns an
empty node object, leaving node configuration to the main manifest. The exec
terminus calls an ENC script
to determine what goes in the node object. Every node might also get
a node definition from the main manifest.
Classes specified in the node object it received from the node terminus.
Classes or resources that are in the site manifest but outside any node definitions.
Classes or resources in the most specific node definition in
site.pp
that matches the current node (ifsite.pp
contains any node definitions). The following notes apply:If
site.pp
contains at least one node definition, it must have a node definition that matches the current node; compilation fails if a match can’t be found.If the node name resembles a dot-separated fully qualified domain name, Puppet makes multiple attempts to match a node definition, removing the right-most part of the name each time. Thus, Puppet would first try
agent1.example.com
, thenagent1.example
, thenagent1
. This behavior isn’t mimicked when calling an ENC, which is invoked only once with the agent’s full node name.If no matching node definition can be found with the node’s name, Puppet tries one last time with a node name of
default
; most users include anode default {}
statement in theirsite.pp
file. This behavior isn’t mimicked when calling an ENC.
Comparing ENCs and node definitions
If you're trying to decide whether to use an ENC or main manifest node definitions (or both), consider the following:
The YAML returned by an ENC isn’t an exact equivalent of a node definition in
site.pp
— it can’t declare individual resources, declare relationships, or do conditional logic. An ENC can only declare classes, assign top-scope variables, and set an environment. So, an ENC is most effective if you’ve done a good job of separating your configurations out into classes and modules.ENCs can set an environment for a node, overriding whatever environment the node requested.
Even if you aren’t using node definitions, you can still use
site.pp
to do things like set global resource defaults.Unlike regular node definitions, where a node can match a less specific definition if an exactly matching definition isn’t found (depending on Puppet’s
strict_hostname_checking
setting), an ENC is called only once, with the node’s full name.
Connect an ENC
Configure two settings to have Puppet Server connect to an external node classifier.
puppet.conf
file:-
Set the
node_terminus
setting toexec
. -
Set the
external_nodes
setting to the path to the ENC executable.
[master]
node_terminus = exec
external_nodes = /usr/local/bin/puppet_node_classifier
ENC output format
An ENC must return either nothing or a YAML hash to
standard out. The hash must contain at least one of classes
or parameters
, or it
can contain both. It can also optionally contain an environment
key.
ENCs exit with an exit code of 0 when functioning normally, and can exit with a non-zero exit code if you want Puppet to behave as though the requested node was not found.
If an ENC returns nothing or exits with a non-zero exit code, the catalog compilation fails with a “could not find node” error, and the node is unable to retrieve configurations.
For information about the YAML format, see yaml.org.
Classes
classes
must be either an array of class names or a hash whose keys
are class names. That is, the following are
equivalent:classes:
- common
- puppet
- dns
- ntp
classes:
common:
puppet:
dns:
ntp:
on
) as
Booleans. Non-parameterized classes can have empty
values.classes:
common:
puppet:
ntp:
ntpserver: 0.pool.ntp.org
aptsetup:
additional_apt_repos:
- deb localrepo.example.com/ubuntu lucid production
- deb localrepo.example.com/ubuntu lucid vendor
Parameters
parameters
key must be a hash of valid variable names and associated
values; these are exposed to the compiler as top-scope variables. Each value can be
a string, number, array, or
hash.parameters:
ntp_servers:
- 0.pool.ntp.org
- ntp.example.com
mail_server: mail.example.com
iburst: true
Environment
environment
must be a string representing the desired environment for this node. This is the only environment used by the node
in its requests for catalogs and
files.environment: production
Complete example
---
classes:
common:
puppet:
ntp:
ntpserver: 0.pool.ntp.org
aptsetup:
additional_apt_repos:
- deb localrepo.example.com/ubuntu lucid production
- deb localrepo.example.com/ubuntu lucid vendor
parameters:
ntp_servers:
- 0.pool.ntp.org
- ntp.example.com
mail_server: mail.example.com
iburst: true
environment: production