Refactoring My First Users Recipe


#1

Hi,

Now that I have a simple unit test with ChefSpec in place, I decided to
move forward with a refactoring.

Here is my spec:

recipes/users_spec.rb:

require ‘spec_helper’

describe ‘masterwrap::users’ do

let(:chef_run) do
ChefSpec::ServerRunner.new do |node, server|
server.create_data_bag(
‘users’, {
‘deploy’ => {
“id” => “deploy”,
“groups” => [ “deploy” ],
“shell” => “/bin/bash”
}
}
)
end.converge(described_recipe)
end

it ‘adds deploy user’ do
expect(chef_run).to create_user(‘deploy’)
end

end

Here is my first iteration that got the specs to pass. I know I am not
really using the users data bag stub/mock:

user ‘deploy’

This implementation obviously is not using the data_bag, so here is my
second iteration, which is using Chef’s users cookbook (1.8.0):

include_recipe ‘users’

users_manage ‘deploy’ do
data_bag 'users’
group_name 'deploy’
action :create
end

Now my spec is failing:

.F

Failures:

  1. masterwrap::users adds deploy user

    Failure/Error: expect(chef_run).to create_user(‘deploy’)

    expected “user[deploy]” with action :create to be in Chef run. Other
    user resources:

    ./spec/unit/recipes/users_spec.rb:26:in `block (2 levels) in <top

(required)>’

Finished in 3.99 seconds (files took 2.89 seconds to load)

2 examples, 1 failure

Failed examples:

rspec ./spec/unit/recipes/users_spec.rb:25 # masterwrap::users adds deploy
user
I am sure it is something simple I am overlooking. I have read and reread
Chef’s documentation for the users cookbook (
https://supermarket.chef.io/cookbooks/users), but nothing is jumping out at
me. Thank you for your help.

Jimmy


#2

Chef runs work in two phases, and you need to understand that to get how Chefspec works.

This video explains it really well, so pause and watch this if you don’t understand it:

Chefspec works by inspecting the resource collection, without actually evaluating it.

In your old code, a resource of type user with name ‘deploy’ was in the resource collection.
In your new code, a resource of type users_manage with name ‘deploy’ is in the resource collection.

So the error message you’re seeing is correct, because Chefspec is telling you that there’s no user resource with name ‘deploy’ in your resource collection. If you’re thinking, “Well, then what is Chefspec good for if it doesn’t tell me what the Chef run would actually do to a system?” then that’s a valid question. While Chefspec definitely has tons of value, it’s not a replacement for the kinds of inspection that Serverspec can do.

I wrote an answer here about which testing tools are appropriate when, but I can go deeper if you need:
http://www.reddit.com/r/devops/comments/2xsq5d/having_a_difficult_time_wrapping_my_head_around/cp3ijba

--Charles

On March 12, 2015 at 2:14:05 PM, Jimmy Huang (jimmy.huang@duragility.com) wrote:
Hi,

Now that I have a simple unit test with ChefSpec in place, I decided to move forward with a refactoring.

Here is my spec:

recipes/users_spec.rb:

require ‘spec_helper’

describe ‘masterwrap::users’ do

let(:chef_run) do
ChefSpec::ServerRunner.new do |node, server|
server.create_data_bag(
‘users’, {
‘deploy’ => {
“id” => “deploy”,
“groups” => [ “deploy” ],
“shell” => “/bin/bash”
}
}
)
end.converge(described_recipe)
end

it ‘adds deploy user’ do
expect(chef_run).to create_user(‘deploy’)
end

end
Here is my first iteration that got the specs to pass. I know I am not really using the users data bag stub/mock:

user 'deploy’
This implementation obviously is not using the data_bag, so here is my second iteration, which is using Chef’s users cookbook (1.8.0):

include_recipe ‘users’

users_manage ‘deploy’ do
data_bag 'users’
group_name 'deploy’
action :create
end
Now my spec is failing:
.F

Failures:

  1. masterwrap::users adds deploy user

    Failure/Error: expect(chef_run).to create_user(‘deploy’)

    expected “user[deploy]” with action :create to be in Chef run. Other user resources:

    ./spec/unit/recipes/users_spec.rb:26:in `block (2 levels) in <top (required)>’

Finished in 3.99 seconds (files took 2.89 seconds to load)

2 examples, 1 failure

Failed examples:

rspec ./spec/unit/recipes/users_spec.rb:25 # masterwrap::users adds deploy user

I am sure it is something simple I am overlooking. I have read and reread Chef’s documentation for the users cookbook (https://supermarket.chef.io/cookbooks/users), but nothing is jumping out at me. Thank you for your help.

Jimmy


#3

Hi Charles,

Thank you so much for taking the time to explain the key difference between
ChefSpec and Serverspec and how that difference ties into how Chef works in
two phases. The video drove home that point, and I can use this exact
example to explain to others in my organize how ChefSpec and Serverspec
complement one another – one looks at the resource collection built; one
checks the outcome of the convergence; and both need to be evaluated.
Thank you again for your help and guidance.

Sincerely,
Jimmy

On Thu, Mar 12, 2015 at 2:30 PM, Charles Johnson charles@chef.io wrote:

Chef runs work in two phases, and you need to understand that to get how
Chefspec works.

This video explains it really well, so pause and watch this if you don’t
understand it:
https://www.youtube.com/watch?v=ZGDdhgoFAec

Chefspec works by inspecting the resource collection, without actually
evaluating it.

In your old code, a resource of type user with name ‘deploy’ was in the
resource collection.
In your new code, a resource of type users_manage with name ‘deploy’ is in
the resource collection.

So the error message you’re seeing is correct, because Chefspec is telling
you that there’s no user resource with name ‘deploy’ in your resource
collection. If you’re thinking, “Well, then what is Chefspec good for if it
doesn’t tell me what the Chef run would actually do to a system?” then
that’s a valid question. While Chefspec definitely has tons of value, it’s
not a replacement for the kinds of inspection that Serverspec can do.

I wrote an answer here about which testing tools are appropriate when, but
I can go deeper if you need:

http://www.reddit.com/r/devops/comments/2xsq5d/having_a_difficult_time_wrapping_my_head_around/cp3ijba

--Charles

On March 12, 2015 at 2:14:05 PM, Jimmy Huang (jimmy.huang@duragility.com)
wrote:

Hi,

Now that I have a simple unit test with ChefSpec in place, I decided to
move forward with a refactoring.

Here is my spec:

recipes/users_spec.rb:

require ‘spec_helper’

describe ‘masterwrap::users’ do

let(:chef_run) do
ChefSpec::ServerRunner.new do |node, server|
server.create_data_bag(
‘users’, {
‘deploy’ => {
“id” => “deploy”,
“groups” => [ “deploy” ],
“shell” => “/bin/bash”
}
}
)
end.converge(described_recipe)
end

it ‘adds deploy user’ do
expect(chef_run).to create_user(‘deploy’)
end

end

Here is my first iteration that got the specs to pass. I know I am not
really using the users data bag stub/mock:

user ‘deploy’

This implementation obviously is not using the data_bag, so here is my
second iteration, which is using Chef’s users cookbook (1.8.0):

include_recipe ‘users’

users_manage ‘deploy’ do
data_bag 'users’
group_name 'deploy’
action :create
end

Now my spec is failing:

.F

Failures:

  1. masterwrap::users adds deploy user

    Failure/Error: expect(chef_run).to create_user(‘deploy’)

    expected “user[deploy]” with action :create to be in Chef run.
    Other user resources:

    ./spec/unit/recipes/users_spec.rb:26:in `block (2 levels) in <top

(required)>’

Finished in 3.99 seconds (files took 2.89 seconds to load)

2 examples, 1 failure

Failed examples:

rspec ./spec/unit/recipes/users_spec.rb:25 # masterwrap::users adds deploy
user
I am sure it is something simple I am overlooking. I have read and
reread Chef’s documentation for the users cookbook (
https://supermarket.chef.io/cookbooks/users), but nothing is jumping out
at me. Thank you for your help.

Jimmy