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