Chapter 6. Controlling Resource Processing

You can control how Puppet utilizes and acts upon resources with metaparameters. Metaparameters are common attributes that can be used with any resource, including both built-in and custom resource types. Metaparameters control how Puppet deals with the resource.

You can find all metaparameters documented at “Metaparameter Reference” on the Puppet docs site.

Adding Aliases

As previously mentioned, every resource in the Puppet manifest must refer to a unique resource. Each resource has one attribute (called namevar) that identifies the unique resource on the node. If the namevar attribute is not set, it defaults to the title as a value. You’ve already seen this in previous examples:

file { '/tmp/testfile.txt':
  ensure  => present,
  path    => '/tmp/testfile.txt',   # this was implicit in earlier example
  content => "holy cow!
",
}

The namevar attribute uniquely identifies the resource manifestation (e.g., the file on disk in this example), therefore it differs for each resource. Refer to the “Resource Type Reference” on the Puppet docs site to find the namevar for a given resource.

To simplify references to resources, you can add an alias or “friendly name” to the resource name. This is an essential technique when the resource’s name or location on disk might change from one node to the other. There are two ways to create an alias.

Specifying an Alias by Title

The first way to provide an alias for a resource is to supply a different value in the title than in the namevar attribute:

file { 'the-testfile':
  ensure  => present,
  path    => '/tmp/testfile.txt',
  content => "holy cow!
",
}

This implicitly creates an alias that can be used as an alternate name for the resource.

Adding an Alias Metaparameter

The alias attribute provides an explicit way to provide a friendly name to a resource. This usage may be more readable to a Puppet novice unaware of implicit aliasing:

file { '/tmp/testfile.txt':
  ensure  => present,
  alias   => 'the-testfile'
  content => "holy cow!
",
}

Preventing Action

The no operation (noop) attribute allows a resource to be evaluated, but prevents a change from being applied during convergence. This can be useful for auditing purposes, or to identify what would change during convergence. For example, to determine if a newer version of the puppet-agent package is available without performing the update, set the attribute to true:

package { 'puppet-agent':
  ensure  => latest,
  noop   => true,
}

When this manifest is processed, if a new package version is available it will report what it would have done:

[vagrant@client ~]$ sudo puppet apply /vagrant/manifests/puppet-agent.pp
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/Package[puppet-agent]/ensure:
  current_value 1.3.6-1.el7, should be 0:1.4.0-1.el7 (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.37 seconds

You can get the same behavior by using the --noop command-line flag on a manifest that doesn’t have the attribute defined:

[vagrant@client ~]$ puppet apply --noop /vagrant/manifests/tmp-testfile.pp
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/Exec[echo-holy-cow]/returns:
  current_value notrun, should be 0 (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.01 seconds

There is no way to override the noop resource attribute with a command-line flag, as the resource attribute has a higher priority than the global option. However, you can place noop = true as a configuration option in the Puppet configuration file, and override that with a command-line flag.

Auditing Changes

The audit attribute defines a list of attributes that you want to track changes to. Define this attribute with an array of attribute names that you wish to track, or the value all. Changes to any of these values will log a message during a puppet apply or puppet inspect run. This could be useful if you don’t want to manage the content of a file, but do want to know every time the content changes:

file { '/etc/hosts':
  audit  => ['content','owner'],
}
file { '/etc/passwd':
  audit  => 'all',
}

This attribute is generally used on resources that Puppet does not manage the values for. If you define this attribute on a resource Puppet manages, you will receive a log notice that Puppet has changed the resource, followed by the audit noticing that Puppet made a change.

Here’s how the preceding manifest would work on the first run:

[vagrant@client ~]$ puppet apply /vagrant/manifests/audit.pp
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/File[/etc/hosts]/content:
  audit change: newly-recorded value {md5}e2b06541983600068fff455f8c11861a
Notice: /Stage[main]/Main/File[/etc/hosts]/owner:
  audit change: newly-recorded value 0
Notice: /Stage[main]/Main/File[/etc/hosts]/group:
  audit change: newly-recorded value 0
Notice: Applied catalog in 0.01 seconds

Now let’s modify the file, and rerun the audit:

[vagrant@client ~]$  echo "# adding junk" | sudo tee -a /etc/hosts
# adding junk
[vagrant@client ~]$ puppet apply /vagrant/manifests/audit.pp
Notice: Compiled catalog for client.example.com in environment production 
Notice: /Stage[main]/Main/File[/etc/hosts]/content: audit change:
  previously recorded value {md5}e2b06541983600068fff455f8c11861a
  has been changed to {md5}28c9f9f5a3d060a500d4b57f9875ba32
Notice: Applied catalog in 0.02 seconds

Defining Log Level

The loglevel attribute allows you to identify the level at which changes to the resource should be logged. The log levels are similar to syslog log levels, and map to those on Unix and Linux systems:

  • debug
  • info (also called verbose)
  • notice
  • warning
  • err
  • alert
  • emerg
  • crit

For example, log at warning level whenever the puppet-agent package is upgraded:

package { 'puppet-agent':
  ensure   => latest,
  loglevel => warning,
}

Filtering with Tags

Tags can be used for selective enforcement of resources—that is, applying only part of a catalog, such as adding packages, without applying other parts of the catalog, such as restarting or stopping services. Let’s look at an example of this.

Tags can be added to resources as a single string, or as an array of strings. The following manifest will tag both the package and the service with the puppet tag, and put an additional package tag on the package resource:

package { 'puppet-agent':
  ensure => present,
  tag    => ['package','puppet'],
}

service { 'puppet':
  ensure => running,
  enable => true,
  tag    => 'puppet',
}

If you run this manifest it will start the Puppet agent, which perhaps isn’t desirable right now. So you can apply the manifest and limit action to resources marked with the package tag:

[vagrant@client ~]$ cd /vagrant/manifests
[vagrant@client ~]$ sudo puppet apply packagetag.pp --tags package
Notice: Compiled catalog for client.example.com in environment production
Notice: Finished catalog run in 0.26 seconds

[vagrant@client ~]$ puppet resource service puppet
service { 'puppet':
  ensure => 'stopped',
  enable => 'false',
}

As you can see, the catalog was applied, but the Puppet service was not started. This demonstrates the power of tags in limiting resource evaluation on demand.

Tip
It wasn’t necessary to add a tag package to the package resource. Puppet automatically adds a tag of the resource type to every resource. We could have applied this manifest with --tags service to affect only the service, even though the service tag isn’t shown in the preceding declaration.

The --tags command-line option can accept multiple comma-separated tags. So you could apply the same manifest with --tags package,service to process both of them.

Skipping Tags

As of Puppet 4.4, tags can be used to selectively skip over tagged resources—that is, applying only the parts of the catalog that don’t match a tag, such as restarting or stopping services. Let’s look at an example of this:

[vagrant@client ~]$ sudo puppet apply packagetag.pp --skip_tags service
Notice: Compiled catalog for client.example.com in environment production
Notice: Finished catalog run in 0.23 seconds

[vagrant@client ~]$ puppet resource service puppet
service { 'puppet':
  ensure => 'stopped',
  enable => 'false',
}

As you can see, the catalog was applied, but the Puppet service was not started. This had the same effect as our previous run, but can be more useful when trying to isolate a smaller set of resources that should be excluded.

Tip
You can use both options together. The --skip_tags configuration option will be applied before --tags, which makes it possible to exclude a set of resources from a larger set of included resources.

Limiting to a Schedule

The schedule metaparameter can be used to limit when Puppet will make changes to a resource. You can define how many times (repeat) within a given hour, day, or week (period) a resource is applied on the node:

schedule { 'twice-daily':
  period => daily,
  repeat => 2,      # apply twice within the period
}

The repeat attribute limits how many times it will be applied within the period. The default is 1. The period can be any of the following values:

  • hourly
  • daily
  • weekly
  • monthly
  • never

The range attribute limits application to specific hours and minutes in a 24-hour period.

schedule { 'after-working-hours':
  period => daily,
  range  => '17:00 - 08:00',             # between 5 p.m. and 8 a.m.
}

The weekday attributes limit application to specific days of the week.

schedule { 'business-hours':
  period  => hourly,
  repeat  => 1,                               # apply once per hour
  range   => '08:00 - 17:00',                 # between 8 a.m. and 5 p.m.
  weekday => ['Mon','Tue','Wed','Thu','Fri'], # on weekdays
}

weekday should be an array whose items are either a number, the three-letter name, or the full English name for a weekday. The following example is valid, albeit confusing to read:

schedule { 'odd-days':
  weekday => ['Mon','3','Friday'],
}

If the range crosses the midnight boundary and the weekday attribute is defined, then the weekday applies to the start of the time period, not when it ends. For example, a resource with the following schedule could be applied any time between Sunday night and Monday morning:

schedule { 'sunday-night':
  range   => '20:00 - 06:00',
  weekday => ['Sunday'],
}

Add the schedule metaparameter to a resource to limit when the resource is applied. For example, if we want to limit upgrades of Puppet until after the normal working day has ended, we might declare it this way:

package { 'puppet-agent':
  ensure   => latest,
  schedule => 'after-working-hours',
}

The value of the schedule metaparameter must be the name of a schedule resource you’ve declared.

Warning
A schedule’s only function is to prevent a resource from being applied outside of the specified range. You have to run Puppet during the range specified for the resource to be applied. If the timing of the Puppet runs and the schedule do not intersect, evaluation of the resource will not occur.

You can find the complete documentation for the schedule resource at “Puppet Types: Schedule” on the Puppet docs site.

Utilizing periodmatch

The schedule resource has an additional (and somewhat confusing) attribute named periodmatch. The current documentation in the Puppet type reference is vague about the meaning of this parameter, so I’m going to spell this one out. periodmatch takes only two values:

distance (default)
This value prevents application of the resource until the period distance (an hour, a day, a week) has passed. If the repeat attribute is specified, the distance is calculated as period/repeat (e.g., four times in a day)
number
This value prevents application of a resource in the period (hour, day, week) of that number. That would be the 5th hour of the day, the 3rd day of the week, the 17th week of the year, and so on.
Warning
When periodmatch is set to number, the repeat attribute cannot be greater than 1.

The effect of this parameter is not intuitive, and you may find yourself coming back to reread this section. Let’s provide some concrete examples. Imagine that you ran puppet apply on a manifest with a file resource at 01:57. Then you deleted the file it created. Say you had a schedule like the following:

schedule { 'once-every-hour':
  period      => hourly,
  periodmatch => distance,
}
file { '/tmp/test.txt':
   ensure   => file,
   schedule => 'once-every-hour',
}

If you ran Puppet every minute with a schedule like this, it would be 02:57, or 60 minutes before the file was re-created.

A periodmatch of number means that the resource is evaluated once within the same number—for example, the second hour. Say you used a schedule like the following and ran it once at 1:57, before deleting the file:

schedule { 'once-in-an-hour':
  period      => hourly,
  periodmatch => number,
}
file { '/tmp/test.txt':
   ensure   => file,
   schedule => 'once-in-an-hour',
}

In this case, the file would be re-created in the first minute of the second hour, only three minutes later!

$ while true; do
    date;
    rm -f /tmp/test.txt;
    puppet apply /vagrant/manifests/schedule.pp;
    sleep 60;
  done

Sun Sep 20 03:57:10 UTC 2015
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/File[/tmp/test.txt]/ensure: created
Notice: Applied catalog in 0.01 seconds

Sun Sep 20 03:58:12 UTC 2015
Notice: Compiled catalog for client.example.com in environment production
Notice: Applied catalog in 0.02 seconds

Sun Sep 20 03:59:13 UTC 2015
Notice: Compiled catalog for client.example.com in environment production
Notice: Applied catalog in 0.02 seconds

Sun Sep 20 04:00:15 UTC 2015
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/File[/tmp/test.txt]/ensure: created
Notice: Applied catalog in 0.01 seconds

When you use the default distance value with a repeat greater than 1, the period is divided evenly by the value of repeat. With a period of daily and a repeat of 4, the resource will be evaluated no sooner than six hours after the last application.

Tip
Keep in mind that schedule only limits when the resource will be evaluated. It does not schedule Puppet to apply the catalog. On the first catalog application after the period expires, Puppet will evaluate the resource again.

If Puppet applies the catalog every 30 minutes (default config), then an hourly schedule will limit the resource evaluation to every other standard run. Using an hourly period with a repeat of 2 will only prevent ad hoc runs in between the normal runs from affecting the resource.

The manifest /vagrant/manifests/schedule.pp defines three hourly schedules and three files using those schedules. To see this in action, apply this manifest in a loop as follows and examine the results:

$ while true; do
    date;
    puppet apply /vagrant/manifests/schedule.pp;
    sleep 60;
  done

Avoiding Dependency Failures

There is a “feature” of Puppet that may surprise you. A resource that is not evaluated because it falls outside the configured schedule will succeed for the purposes of dependency evaluation. This means that if the resource creates something that a later resource utilizes, like a configuration file, the dependent resource will fail.

Here’s an example:

schedule { 'workhours':
  range => '08:00 - 17:00',
}

file { '/tmp/workhours.txt':
  ensure   => file,
  content  => 'Open for business',
  schedule => 'workhours',
}

exec { 'use file':
  path    => '/bin:/usr/bin',
  command => 'cat /tmp/workhours.txt',
  require => File['/tmp/workhours.txt'],
}

If we apply this manifest outside of work hours, the file is not created because it falls outside the schedule. The following exec resource then fails because a file it needs doesn’t exist:

[vagrant@client ~]$ puppet apply /vagrant/manifests/unscheduled.pp
Notice: Compiled catalog for client.example.com in environment production
Notice: /Stage[main]/Main/Exec[use file]/returns:
  cat: /tmp/workhours.txt: No such file or directory
Error: cat /tmp/workhours.txt returned 1 instead of one of [0]
Error: /Stage[main]/Main/Exec[use file]/returns: change from notrun to 0 failed:
  cat /tmp/workhours.txt returned 1 instead of one of [0]
Notice: Applied catalog in 0.02 seconds

There are a few ways to avoid this problem.

  • Assign the same schedule to both resources.
  • Use onlyif to check if the file exists first (only works with exec resources).
  • Run Puppet with --ignoreschedules to ensure that all resources are created.

The final suggestion is perhaps the single best option. The first time you run Puppet to initialize a new node, you may want to enable ignoreschedules to ensure that every resource is created. The schedule will prevent further changes to those resources until the specified range of time.

Declaring Resource Defaults

You can declare defaults for all resources of a given type. If a resource declaration of the same type does not explicitly declare the attribute, then the attribute value from the resource default will be used.

Resource defaults are declared with a capitalized resource type and no title. For example, the following resource definition would limit package evaluation to after working hours:

Package {
  schedule => 'after-working-hours',
}

Defaults can be defined multiple times, causing confusion for the people who have to debug the code. A default specified later in the manifest affects resources above it. Avoid this whenever possible.

Best Practice

Declare resource defaults at the top of the manifest for easy reading purposes.

Resource defaults also bleed into other code that is called or declared within the manifest scope. This can have surprising consequences. A more readable and maintainable method is to place the default attribute values into a hash, and add it to resources with the splat operator, as shown in “Defining Attributes with a Hash”.

The problems with resource defaults and variable scope are explained in “Understanding Variable Scope”.

Reviewing Resource Processing

This chapter introduced you to attributes that control how resources are processed:

  • alias provides friendly names for resources with complicated or variable titles.
  • noop prevents changes to the resource.
  • audit logs changes to a resource outside of Puppet.
  • loglevel controls log output on a per-resource basis.
  • tags identifies resources to be evaluated on a filtered Puppet run.
  • schedule limits when or how often changes to a resource are permitted.
  • An uppercase first letter on a resource declaration assigns default attribute values.

Using these attributes provides fine-grained control over how and when your resources are evaluated.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset