puppetrspec-puppet

Rspec-Puppet - how to test metaparameter 'require' of a resource in a Puppet class or defined type?


When I have a Puppet class which declares a resource with metaparameter 'require', how do I test this resource and the metaparameter in the spec test?

Excerpt of class showing resource declaration

  $patch = 'jboss-eap-7.4.11-patch.zip'
  wildfly::patch::offline { 'Atualiza JBoss para 7.4.11':
    source  => "/tmp/${patch}",
    require => Class['wildfly'],
  }

This is what I could think of so far, then tested, and failed miserably:

Spec test 1st attempt

  let(:pre_condition) { ['define wildfly::patch::offline($source) {}'] }
  it do
    is_expected.to contain_wildfly__patch__offline('Atualiza JBoss para 7.4.11').with(
      'source' => '/tmp/jboss-eap-7.4.11-patch.zip',
      'require' => 'Class["wildfly"]'
    )
  end

Error

       expected that the catalogue would contain Wildfly::Patch::Offline[Atualiza JBoss para 7.4.11] with require set to "Class[\"wildfly\"]" but it is set to Class[Wildfly]{:name=>"Wildfly"}
     # ./spec/classes/jboss_74_spec.rb:23:in `block (2 levels) in <top (required)>'

Spec test correction attempt from the error message

Weird naming it is, but I trust error messages

    is_expected.to contain_wildfly__patch__offline('Atualiza JBoss para 7.4.11').with(
      'source' => '/tmp/jboss-eap-7.4.11-patch.zip',
      'require' => 'Class[Wildfly]{:name=>"Wildfly"}'
    )

New error

       expected that the catalogue would contain Wildfly::Patch::Offline[Atualiza JBoss para 7.4.11] with require set to "Class[Wildfly]{:name=>\"Wildfly\"}" but it is set to Class[Wildfly]{:name=>"Wildfly"}
     # ./spec/classes/jboss_74_spec.rb:23:in `block (2 levels) in <top (required)>'

Also tried without success

I started frobnicating with different single/double/no quotes, only to get new errors with different quoting.

How do I get past this mess?


Solution

  • You're dancing around the correct syntax. To express a resource reference to RSpec-Puppet, you omit quotation marks around the resource title (which in most cases are optional in manifest code anyway). But RSpec-Puppet's messaging has misled you: the correct form does not include a property list. The wanted string representation of your resource reference should be simply 'Class[wildfly]'. So:

        is_expected.to contain_wildfly__patch__offline('Atualiza JBoss para 7.4.11').with(
          'source' => '/tmp/jboss-eap-7.4.11-patch.zip',
          'require' => 'Class[wildfly]'
        )
    

    The full rules are documented in the RSpec-Puppet documentation of the specific tests for resource relationships:

    The values [] must be in the format used in the Puppet catalogue (which is slightly different to the way they're written in a Puppet manifest).

    • The resource titles must be unquoted (Package[apache] instead of Package['apache'])
    • One title per resource ([Package[apache], Package[htpasswd]] instead of Package[apache, htpasswd])
    • If referencing a class, it must be fully qualified and should not have a leading :: (Class[apache::service] instead of Class[::apache::service])

    Note also: resource titles are case sensitive, so it is either significant or erroneous that RSpec is telling you that the relationship is actually on Class[Wildfly] (capital 'W') instead of on Class['wildfly'] (small 'w'). Package and class names should be lowercase, so I'm not sure what's going on here, but perhaps it's another RSpec quirk.