Some Notes on an InSpec Resource

This post will cover 2 topics:

  1. Writing a custom InSpec resource and
  2. Vendoring gems as part of the profile.

Custom InSpec Resource

The custom resource we’re going to write is for verifying the existence of is Perl Modules on a box.

Disclaimer: This profile takes into account that the instmodsh command is installed, and that the profile is being run on Linux (for the ruby PTY library used by the ruby_expect gem).

Anyways, here’s the pseudo-code:

  • Use instmodsh to determine the perl modules installed
  • Parse that out into an array
  • Finally specify operations on that array.

Some functions of the resource we would like to be able to check for the existence of perl modules and if specific modules are installed or not installed. An example describe block from a profile would be:

describe perl_modules do
its('content') { should include('Perl') }
its('content') { should_not include('Foo') }
it { should exist }

Checking the existence with it { should exist } was straight forward from the documentation, however getting theits('content') matcher to work was not exactly as straight forward. After some trial and error I found a params class variable of type Hash I added a key of content with a value of our array of perl modules, i.e. @params['content'] = modules. We were able to use the include('Perl’) inside the block because the type of the value returned from the @params['content'] is an Array, which responds to the include? method. From this we can determine that any time you wish to use its('x') you must have@params['x'] = y in the resource definition, and you can include within the it(s) block any operations on the returned class.

Here’s the real code:

Vendoring Gems

It’s not always straight forward about how to use gems within Chef, as there are many ways. With InSpec it’s a little different, you have limited options when you want to guarantee that a gem exists on the system executing the profile. For this Custom Resource I chose to vendor the gem we needed. This vendoring can be done by downloading the gem into a specified location with the following command:

gem install --install-dir libraries/vendor --no-document ruby_expect

Once vendored, to gain access to this gem we must modify Rubies $LOAD_PATH by adding on all of these gems installed to a local directory by adding it to the $LOAD_PATH array.

$LOAD_PATH.unshift(*Dir[File.expand_path('../vendor/gems/**/lib', __FILE__)])

Here’s a cool video explaining Rubies $LOAD_PATH.

Thanks for letting me bore you!

Skyler Layne

Written by

Senior DevOps Specialist at @Indellient. Avid coffee drinker, early riser, cat lover, king of um. m.k.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade