Skip to content

Instantly share code, notes, and snippets.

@kwilczynski
Last active July 6, 2023 08:35
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save kwilczynski/c271f251ea7f48ba99b3 to your computer and use it in GitHub Desktop.
Save kwilczynski/c271f251ea7f48ba99b3 to your computer and use it in GitHub Desktop.
Recipe / Role check in Chef

If you want to check whether a node run_list includes a specific role (upon expansion), then you could use role? method on the Node object:

node.role?('name')

Alternatively, you can see whether either would work for you:

node.roles.include?('name')

node.run_list?('role[name]')

There exist also node.run_state[:seen_recipes], but it often has different use case.

Methods on the Node object:

recipe? https://github.com/opscode/chef/blob/master/lib/chef/node.rb#L247

role? https://github.com/opscode/chef/blob/master/lib/chef/node.rb#L259

run_list? https://github.com/opscode/chef/blob/master/lib/chef/node.rb#L288

All of the above should be present in reasonably up-to-date version of the Chef Client.

Let's see whether they work ... Details about the node:

[chef@C3394864441 ~]$ knife node show ChefDK
Node Name:   ChefDK
Environment: _default
FQDN:        C3394864441.domain
IP:          10.160.200.69
Run List:    role[base_workstation]
Roles:       base_workstation
Recipes:     workstation, workstation::default
Platform:    centos 6.5
Tags:

Details about the role:

[chef@C3394864441 ~]$ knife role show base_workstation
chef_type:           role
default_attributes:
  chef_client:
    interval: 60
    splay:    30
  push_jobs:
    package_url: https://s3.amazonaws.com/opscode-private-chef/el/6/x86_64/opscode-push-jobs-client-1.0.2-1.el6.x86_64.rpm
description:         Base role for workstation nodes
env_run_lists:
json_class:          Chef::Role
name:                base_workstation
override_attributes:
run_list:            recipe[workstation]
[chef@C3394864441 ~]$

Testing to see what is included in the run_list (running chef-shell in client mode):

[chef@C3394864441 ~]$ sudo chef-shell -z
loading configuration: /etc/chef/client.rb
Session type: client
Loading....resolving cookbooks for run list: ["workstation"]
Synchronizing Cookbooks:
  - workstation
.done.

This is the chef-shell.
 Chef Version: 11.14.0.rc.2
 http://www.opscode.com/chef
 http://docs.opscode.com/

run `help' for help, `exit' or ^D to quit.

Ohai2u chef@C3394864441.domain!
chef > node.recipe?('workstation')
 => true
chef > node.recipe?('base_workstation')
 => false
chef > node.role?('workstation')
 => false
chef > node.role?('base_workstation')
 => true
chef > node.run_list?('workstation')
 => false
chef > node.run_list?('base_workstation')
 => false
chef > node.run_list?('recipe[workstation]')
 => false
chef > node.run_list?('role[workstation]')
 => false
chef > node.run_list?('role[base_workstation]')
 => true
chef >

We can see that all methods work, but only recipe? looks for given recipes in the expanded run_list. For instance, base_workstation will expand into workstation at the beginning of the Chef client run, so all the recipes it includes will be applied accordingly and in order during the node convergence.

Other ideas and/or explanation can be found here: http://stackoverflow.com/questions/22865769/how-to-check-if-recipe-has-been-included-using-include-recipe

@shortdudey123
Copy link

@lamont-granquist do you mean node.recipe??
I don't see anything in the codebase called recipes?

    NoMethodError
    -------------
    Undefined node attribute or method `recipes?' on `node'

Chef 12.6.0

Copy link

ghost commented Oct 21, 2016

node.read('roles').include?('role_name')

@revanthreddy36
Copy link

revanthreddy36 commented Dec 15, 2016

I have a block of code in my recipe like this :

if (node.chef_environemnt == "QA" && node.role?('rolename'))
  group 'greoupname' do
  action :create
 end 
end

How do I test this condition while using chefspec tests..The following code works for testing with environemnts.
my recipe_spec.rb has this

require 'spec_helper'

 describe 'cookbook::recipe' do
  let(:chef_run) do
  runner = ChefSpec::SoloRunner.new(platform: 'redhat',version:'6.5') do |node| 
    env = Chef::Environment.new
    env.name environment             # using a variable here so we can change it in other contexts
    allow(node).to receive(:chef_environment).and_return(env.name)
    allow(Chef::Environment).to receive(:load).and_return(env)
    end.converge 'cookbook::recipe'
end

context 'in QA' do
  let(:environment) { 'QA' }         # change the environment set up above in let(:chef_run)
it 'creates group solr' do
    expect(chef_run).to create_group('groupname')
  end
end 

the above test case works perfectly. Can somebody help me how to mock a role and use that in conjunction with an environemnt. Like I want to test a block of code that runs in QA environemnt and only on those nodes which have a particular role.

Thanks in advance !

@kwilczynski
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment