How to Check Chef Environment in Recipes with Practical Examples


1 views

When working with Chef, you'll often need to execute certain resources or logic only in specific environments. The environment can be checked directly in your recipe without needing to perform complex searches.

The most straightforward way to check the current environment is using node.chef_environment:

if node.chef_environment == 'dev'
  cookbook_file '/path/to/file' do
    source 'file.txt'
    owner 'root'
    group 'root'
    mode '0644'
    action :create
  end
end

While the search method mentioned in documentation works, it's indeed unnecessary for simple environment checks. Here's why the search approach isn't ideal for your case:

# Not recommended for simple environment checks
qa_nodes = search(:node, "chef_environment:QA")
qa_nodes.each do |qa_node|
  # This would execute for all QA nodes, not what you want
end

For more complex scenarios where you need to check multiple environments or combine conditions:

case node.chef_environment
when 'dev', 'staging'
  # Resources specific to development and staging
  package 'debug-tools' do
    action :install
  end
when 'production'
  # Production-specific resources
  package 'security-audit' do
    action :install
  end
end

Using node.chef_environment directly is:

  • More performant - no search queries needed
  • Simpler to read and maintain
  • More precise for single-node operations
  • Works even if Chef server isn't available

Here's a complete example showing environment-specific file deployment:

# Only deploy the development config file in dev environment
if node.chef_environment == 'dev'
  cookbook_file '/etc/app/dev_config.conf' do
    source 'dev_config.conf'
    owner 'appuser'
    group 'appuser'
    mode '0600'
    action :create
    notifies :restart, 'service[app]', :delayed
  end
else
  file '/etc/app/dev_config.conf' do
    action :delete
    only_if { ::File.exist?('/etc/app/dev_config.conf') }
  end
end

service 'app' do
  action :nothing
end

When working with Chef, you'll often need to execute resources conditionally based on the current environment. The cookbook_file resource example you mentioned is a common use case where you want to deploy files only in specific environments like development.

The simplest way to check the current environment is through the node.chef_environment attribute:

if node.chef_environment == 'dev'
  cookbook_file '/path/to/file' do
    source 'my_file'
    owner 'root'
    group 'root'
    mode '0644'
  end
end

The documentation example you referenced using search(:node, "chef_environment:QA") is actually for a different use case - when you need to find all nodes in a particular environment. This would be useful for scenarios like:

# Apply configuration to all QA nodes
search(:node, "chef_environment:QA").each do |qa_node|
  template "/etc/#{qa_node['hostname']}/config" do
    source 'config.erb'
    variables(
      :hostname => qa_node['hostname'],
      :ipaddress => qa_node['ipaddress']
    )
  end
end

For more complex environment-based logic, you can use case statements or helper methods:

case node.chef_environment
when 'dev'
  include_recipe 'development_tools'
  cookbook_file '/etc/dev_config' do
    source 'development.conf'
  end
when 'production'
  include_recipe 'security_hardening'
end
  • Always use the exact environment name (case-sensitive)
  • Consider using node attributes for environment-specific values
  • Document your environment conditions clearly
  • Test environment conditions in your ChefSpec tests