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.
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 examplecontent=>"holy cow!\n",}
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.
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!\n",}
This implicitly creates an alias that can be used as an alternate name for the resource.
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~]$sudopuppetapply/vagrant/manifests/puppet-agent.ppNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/Package[puppet-agent]/ensure:current_value1.3.6-1.el7,shouldbe0:1.4.0-1.el7(noop)Notice:Class[Main]:Wouldhavetriggered'refresh'from1eventsNotice:Stage[main]:Wouldhavetriggered'refresh'from1eventsNotice:Appliedcatalogin0.37seconds
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~]$puppetapply--noop/vagrant/manifests/tmp-testfile.ppNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/Exec[echo-holy-cow]/returns:current_valuenotrun,shouldbe0(noop)Notice:Class[Main]:Wouldhavetriggered'refresh'from1eventsNotice:Stage[main]:Wouldhavetriggered'refresh'from1eventsNotice:Appliedcatalogin0.01seconds
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.
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~]$puppetapply/vagrant/manifests/audit.ppNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/File[/etc/hosts]/content:auditchange:newly-recordedvalue{md5}e2b06541983600068fff455f8c11861aNotice:/Stage[main]/Main/File[/etc/hosts]/owner:auditchange:newly-recordedvalue0Notice:/Stage[main]/Main/File[/etc/hosts]/group:auditchange:newly-recordedvalue0Notice:Appliedcatalogin0.01seconds
Now let’s modify the file, and rerun the audit:
[vagrant@client~]$echo"# adding junk"|sudotee-a/etc/hosts# adding junk[vagrant@client~]$puppetapply/vagrant/manifests/audit.ppNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/File[/etc/hosts]/content:auditchange:previouslyrecordedvalue{md5}e2b06541983600068fff455f8c11861ahasbeenchangedto{md5}28c9f9f5a3d060a500d4b57f9875ba32Notice:Appliedcatalogin0.02seconds
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:
debuginfo (also called verbose)noticewarningerralertemergcritFor example, log at warning level whenever the puppet-agent package is upgraded:
package{'puppet-agent':ensure=>latest,loglevel=>warning,}
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~]$sudopuppetapplypackagetag.pp--tagspackageNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:Finishedcatalogrunin0.26seconds[vagrant@client~]$puppetresourceservicepuppetservice{'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.
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.
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~]$sudopuppetapplypackagetag.pp--skip_tagsserviceNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:Finishedcatalogrunin0.23seconds[vagrant@client~]$puppetresourceservicepuppetservice{'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.
--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.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:
hourlydailyweeklymonthlyneverThe 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 hourrange=>'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.
You can find the complete documentation for the schedule resource at “Puppet Types: Schedule” on the Puppet docs site.
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)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)numberperiodmatch 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!
$whiletrue;dodate;rm-f/tmp/test.txt;puppetapply/vagrant/manifests/schedule.pp;sleep60;doneSunSep2003:57:10UTC2015Notice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/File[/tmp/test.txt]/ensure:createdNotice:Appliedcatalogin0.01secondsSunSep2003:58:12UTC2015Notice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:Appliedcatalogin0.02secondsSunSep2003:59:13UTC2015Notice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:Appliedcatalogin0.02secondsSunSep2004:00:15UTC2015Notice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/File[/tmp/test.txt]/ensure:createdNotice:Appliedcatalogin0.01seconds
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.
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:
$whiletrue;dodate;puppetapply/vagrant/manifests/schedule.pp;sleep60;done
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~]$puppetapply/vagrant/manifests/unscheduled.ppNotice:Compiledcatalogforclient.example.cominenvironmentproductionNotice:/Stage[main]/Main/Exec[usefile]/returns:cat:/tmp/workhours.txt:NosuchfileordirectoryError:cat/tmp/workhours.txtreturned1insteadofoneof[0]Error:/Stage[main]/Main/Exec[usefile]/returns:changefromnotrunto0failed:cat/tmp/workhours.txtreturned1insteadofoneof[0]Notice:Appliedcatalogin0.02seconds
There are a few ways to avoid this problem.
onlyif to check if the file exists first (only works with exec resources).--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.
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.
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”.
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.Using these attributes provides fine-grained control over how and when your resources are evaluated.