ChefSpec Encrypted Data Bag Items

I have read through some other threads and data on the web and have found that the syntax mentioned here (https://github.com/sethvargo/chefspec/issues/249) requires me to use this syntax in my recipe code:

Chef::EncryptedDataBagItem.load(‘test’,‘item’,‘secret’)

rather than the syntax I had been using:

data_bag_item(‘test’,‘item’,‘secret’)

For example, if I try to stub the data bag item call, I get this error:

  Failure/Error:
    stub_data_bag_item('ff_iblogix', 'peter','peterkey').and_return(
      { 'db' => 'iblogix'}
    )

  ArgumentError:
    wrong number of arguments (3 for 2)

And if I change the stub to have only two arguments then my recipe fails to compile with a similar error, “wrong number of arguments (3 for 2)”

Just wondering if I’m doing something wrong in my stub or whether the data_bag_item syntax is out of date.

From the Chef docs on data_bag_item:

If secret is not specified, the chef-client looks for a secret at the path specified by the encrypted_data_bag_secret setting in the client.rb file.

So, in your recipe(s), do is this:

data_bag_item 'test', 'item'

and, in your tests, you either stub the data bag item or, for an experience more like what you’d have in production, you can have ChefSpec use a Chef server.

If, however, you have the third argument to supply a secret directly, I think ChefSpec will act exactly how you’ve experienced.

Thanks Jeff. I have been passing the secret directly in recipes, so I do want to have a third argument. I had read about using the ServerRunner but it isn’t obvious to me how that solves my problem. I still need to provide the data bag contents to it some how. From what I can tell the ServerRunner doesn’t provide a method for creating an encrypted data bag.

Well, the idea is, in a test run, you wouldn’t actually be dealing with an encrypted data bag. That’s one reason why the design of data_bag_item allows for automatically handling encrypted data bags if necessary.

In our case, we use the encrypted_data_bag_secret setting in client.rb (which is set as part of an instance’s bootstrap), and omit the third arg (secret). In our test cases, we have test data bag items set up, and validate against those non-sensitive test values.

Have you tried just using the data bag mocking available via the SoloRunner? While still leaving data_bag_item as-is in your recipe. E.g.,

describe 'example::default' do
  before do
    allow(Chef::EncryptedDataBagItem).to receive(:load).with('users', 'svargo').and_return(...)
  end
end

You have given me some ideas. The unit test doesn’t actually deal with the encrypted data, I just needed the recipe to converge. I had not considered setting the encrypted_data_bag_secret in the client.rb. I have been using the ServerRunner because I needed to access Ohai variables.