Friday, December 15, 2017

Today, I was trying to experiment a bit with the go programming language.  I wanted to get started, but the 'install' section of the golang site seemed a bit daunting, and I figured I should use a tool similar to 'RVM' or 'rbenv' from the ruby space for go.  I discovered, but ran into a small hiccup.  The install instructions were to pipe some commands into a bash shell, but after running them, the `gvm` command appeared to be invoking something else!  

From the output, it appeared to be sdkman, which previously was called gvm for 'groovy version manager'. It appears that the install of sdk man places it's files into ~/.sdkman, in addition to calling thing in all three of ~/.profile, ~/.bashrc, and ~/.bash_profile.  I had to explicitly clear out the statements sourcing the sdkman binaries to allow gvm to function properly.  

After clearing out sdkman, I was able to successfully get the latest go installed (after installing go 1.4 from a binary, due to the source compile failing).  `which gvm` now pointted at the go gvm, instead of sdkman!

Tuesday, January 10, 2017

rspec-puppet test with array parameter

Today I stumbled onto something that was much harder than I expected it to be while trying to write an rspec-puppet test.

Say you have a resource with a parameter that is an array, and you only want to validate that the array contains an element.

In our case, say that we have the following code somewhere in our puppet manifests

        host { 'foo.local':
          ip => '',
          host_aliases => [ 'foo1.local', 'foo2.local' ],

It is pretty direct to validate the exact array inside of an rspec-puppet test

    it { should contain_host('foo.local').with_host_aliases( ['foo1.local', 'foo2.local'] ) }

But that requires a very specific 'expected' value to be passed into the matcher.  What if we just wanted to see if the parameter array includes a given value?  

In a conversation about his problem in the #voxpupuli channel on irc@freenode, dev_el_ops mentioned "one of the design problems of rspec-pupet is that it  doesn't expose property values to the regular rspec matchers"

Since we couldn't get the values directly from the matchers, I had to come up with a different way to approach the problem, which is not quite as readable as I would have wanted.

    it {
        host_aliases = catalogue.resource('host', 'foo.local').send(:parameters)[:host_aliases]
        expect(host_aliases).to include('foo1.local')

Lets break down what is happening.  catalogue.resource('host', 'foo.local') will fetch us the catalog's resource object of type 'host' with the title 'foo.local'.  we can then use 'send' to call the private parameters method on the object to get back it's parameter hash, which we then reference the :host_aliases key to retrieve our array.  

Once we have the array (stored in host_aliases), we can then use a simple 'expect' call with an 'include' matcher to check that the given array includes the value we expect.

Here is a gist of the entire example.