Puppet: Test if a virtual Resource exists or is defined

puppet

Previously on ServerFault, it was shown how to test if a Resource was defined:
Puppet: Test if Resource is defined, or create it

if defined(File["/tmp/foo"]) {
  alert("/tmp/foo is defined")
} else {
  alert("/tmp/foo is not defined")
}

I'd like to test if a virtual resource is defined or exists, before realizing it via collector, but it doesn't seem to work with the same syntax.

create_resource('@package',hiera_hash('packages',{}),{})
if !defined(@Package['foo']) {
  alert('Hiera screwed up, critical virtual package is missing')
}
# Realize the critical packages
Package<| groups == critical |>

This gets me:
Error: Could not parse for environment production: Virtual (@) can only be applied to a Resource Expression at test.pp..

The reason is that I want to do the realize via create_resources and collectors, and as testing, throw an error if it's not actually creating some critical virtual resource.

Edit 2014/11/12 19:07 UTC
One of the answers suggested this instead, but it doesn't work, pasting it here because the answer comment box is too small.

class base::test1 {
  @package { 'cookietool':
    ensure => 'present',
  }
  realize(Package['cookietool'])
}

base::test2 has the identical content.

node testbox {
  include base::test1
  include base::test2 
}

This fails with the following error:

Error: Failed to compile catalog for node testbox: Evaluation Error: Error while evaluating a Resource Statement, Duplicate declaration: Package[cookietool] is already declared in file /var/lib/puppet/checkouts/environments/production/modules/base/manifests/test1.pp:2; cannot redeclare at /var/lib/puppet/checkouts/environments/production/modules/base/manifests/test2.pp:2 at /var/lib/puppet/checkouts/environments/production/modules/base/manifests/test2.pp:2:3 on node testbox

Best Answer

By definition, a virtual resource is not "defined" until it has been realized.

As with standard resources, you may only declare virtual resources once, but they can be realized many times - this is one of the major reasons why they're used.

Example

modules/packages/init.pp

class packages {
  @package { 'git':
    ensure => present,
  }
}

modules/git/init.pp

class git {
  realize Package['git']
}

modules/mymodule/init.pp

class mymodule {
  realize Package['git']
}

manifests/site.pp

node 'mynode' {
  include packages
  include git
  include mymodule
}

This will compile and ensure that the git package is installed.

Related Topic