Virtual resources

A virtual resource declaration specifies a desired state for a resource without enforcing that state. Puppet manages the resource by realizing it elsewhere in your manifests. This divides the work done by a normal resource declaration into two steps. Although virtual resources are declared once, they can be realized any number of times, similar to a class.

Purpose

Virtual resources are useful for:
  • Resources whose management depends on at least one of multiple conditions being met.

  • Overlapping sets of resources required by any number of classes.

  • Resources which should only be managed if multiple cross-class conditions are met.

Because they both offer a safe way to add a resource to the catalog in multiple locations, virtual resources can be used in some of the same situations as classes. The features that distinguish virtual resources are:
  • Searchability via resource collectors, which helps to realize overlapping clumps of virtual resources.

  • Flatness, such that you can declare a virtual resource and realize it a few lines later without having to clutter your modules with many single-resource classes.

Syntax

Virtual resources are used in two steps: declaring and realizing. In this example, the apache class declares a virtual resource, and both the wordpress and freight classes realize it. The resource is managed on any node that has the wordpress or freight classes applied to it.

Declare: modules/apache/manifests/init.pp
@a2mod { 'rewrite':
  ensure => present,
} # note: The a2mod resource type is from the puppetlabs-apache module.
Realize: modules/wordpress/manifests/init.pp
realize A2mod['rewrite']
Realize again: modules/freight/manifests/init.pp
realize A2mod['rewrite']
To declare a virtual resource, prepend @ (the “at” sign) to the resource type of a normal resource declaration:
@user {'deploy':
  uid     => 2004,
  comment => 'Deployment User',
  group   => 'www-data',
  groups  => ["enterprise"],
  tag     => [deploy, web],
}
To realize one or more virtual resources by title, use the  realize  function, which accepts one or more resource references:
realize(User['deploy'], User['zleslie'])
Note: The realize function can be used multiple times on the same virtual resource and the resource is only managed once.
resource collector realizes any virtual resources that match its search expression:
User <| tag == web |>
If multiple resource collectors match a given virtual resource, Puppet will only manage that resource once.
Note: A collector also collects and realizes any exported resources from the current node. If you use exported resources that you don’t want realized, take care to exclude them from the collector’s search expression. Also, a collector used in an override block or a chaining statement will also realize any matching virtual resources.

Behavior

A virtual resource declaration does not manage the state of a resource. Instead, it makes a virtual resource available to resource collectors and the realize function. When a resource is realized, Puppet manages its state.

Unrealized virtual resources are included in the catalog, but are marked inactive.

Note: Virtual resources do not depend on evaluation order. You can realize a virtual resource before the resource has been declared.
CAUTION: The realize function causes a compilation failure when attempting to realize a virtual resource that has not been declared. Resource collectors fail silently when they do not match any resources.
When a virtual resource is contained in a class, it cannot be realized unless the class is declared at some point during the compilation. A common pattern is to declare a class full of virtual resources and then use a collector to choose the set of resources you need:
include virtual::users
User <| groups == admin or group == wheel |>
Note: You can declare virtual resources of defined resource types. This causes every resource contained in the defined resource to behave virtually — they are not managed unless their virtual container is realized.
Virtual resources are evaluated in the run stage in which they are declared, not the run stage in which they are realized.