Foodcritic is a helpful lint tool you can use to check your Chef cookbooks for common problems.
It comes with 112 built-in rules that identify problems ranging from simple style inconsistencies to difficult to diagnose issues that will hurt in production.
Various nice people in the Chef community have also written extra rules for foodcritic that you can install and run. Or write your own!
It's easy to get started with Foodcritic in Chef-DK already
$ foodcritic my_cookbook_dir
style
attributes
Use strings rather than symbols when referencing node attributes. This warning will be shown if you reference a node attribute using symbols.
This example would match the FC001 rule because node[:cookbook][:package]
accesses node attributes with symbols
This modified example would not match the FC001 rule:
# Don't do this
package node[:cookbook][:package] do
action :install
end
package node['cookbook']['package'] do
action :install
end
style
strings
When you declare a resource in your recipes you frequently want to reference dynamic values such as node attributes. This warning will be shown if you are unnecessarily wrapping an attribute reference in a string.
This example would match the FC002 rule because the version
attribute has been unnecessarily quoted.
This modified example would not match the FC002 rule:
# Don't do this
package 'mysql-server' do
version "#{node['mysql']['version']}"
action :install
end
# Do this instead
package 'mysql-server' do
version node['mysql']['version']
action :install
end
This rule has been deprecated. Chef 12.11 switched Chef Solo to use Chef Local mode which eliminates the need to avoid server specific Chef functionality in recipes. With that change this rule became obsolete.
portability
services
This warning is shown if you are starting or stopping a service using the
Chef execute
resource rather than the more idiomatic service
resource.
You can read more about the service resource here:
This example would match the FC004 rule because it uses execute
for
service control. There is no reason to use execute because the service
resource exposes the start_command
attribute to give you full
control over the command issued.
This modified example would not match the FC004 rule:
# Don't do this
execute 'start-tomcat' do
command '/etc/init.d/tomcat6 start'
action :run
end
# Do this instead
service 'tomcat' do
action :start
end
style
When writing Chef recipes you have the full power of Ruby at your disposal. One of the cases where this is helpful is where you need to declare a large number of resources that only differ in a single attribute - the canonical example is installing a long list of packages.
This example matches the FC005 rule because all the resources of type
package
differ only in a single attribute - the name of the package
to be upgraded. This rule is very simple and looks only for resources
that all differ in only a single attribute. For example - if only one
of the packages specified the version then this rule would not match.
This modified example would not match the FC005 rule. It takes advantage of the fact that Chef processes recipes in two distinct phases. In the first ‘compile’ phase it builds the resource collection. In the second phase it configures the node against the resource collection.
Don’t worry about changing your recipe if it already does what you want - the amount of Ruby syntactic sugar to apply is very much a matter of personal taste. Note that this rule also isn’t clever enough yet to detect if your resources are wrapped in a control structure and not suitable for ‘rolling up’ into a loop.
# You could do this
package 'erlang-base' do
action :upgrade
end
package 'erlang-corba' do
action :upgrade
end
package 'erlang-crypto' do
action :upgrade
end
package 'rabbitmq-server' do
action :upgrade
end
# It's shorter to do this
%w(erlang-base erlang-corba erlang-crypto rabbitmq-server).each do |pkg|
package pkg do
action :upgrade
end
end
correctness
files
When setting file or directory permissions via the mode attribute you should either quote the octal number or ensure it is specified to five digits. Otherwise the permissions that are set after Ruby coerces the number may not match what you expect.
These modified examples would not match the FC006 rule:
# Don't do this
directory '/var/lib/foo' do
owner 'root'
group 'root'
mode 644
action :create
end
# This is ok
directory '/var/lib/foo' do
owner 'root'
group 'root'
mode '644'
action :create
end
# And so is this
directory '/var/lib/foo' do
owner 'root'
group 'root'
mode 00644
action :create
end
correctness
metadata
This warning is shown when you include a recipe that is not in the current cookbook and not defined as a dependency in your cookbook metadata. This is potentially a big problem because things will blow up if the necessary dependency cannot be found when Chef tries to converge your node. For more information refer to the Chef metadata page:
The fix is to declare the cookbook of the recipe you are including as a
dependency in your metadata.rb
file.
You may also see this warning if foodcritic has not been able to infer the name of your cookbook correctly when the cookbook directory does not match the name of the cookbook specified in the include.
Assuming you have a recipe that had the following line:
Then to remove this warning you would add the apache2
cookbook as a
dependency to your own cookbook metadata in the metadata.rb
file at
the root of your cookbook.
include_recipe 'apache2::default'
depends 'apache2'
metadata
supermarket
This warning is shown if you used knife cookbook create
to create a new
cookbook and didn’t override the maintainer and maintainer email. You need
to set these to real values in metadata.rb
or run knife again with the
real values.
This modified example would not match the FC008 rule:
# Don't do this
maintainer 'YOUR_COMPANY_NAME'
maintainer_email 'YOUR_EMAIL'
license 'All rights reserved'
description 'Installs/Configures example'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.0.1'
# Do this instead
maintainer 'Example Ltd'
maintainer_email 'postmaster@example.com'
license 'All rights reserved'
description 'Installs/Configures example'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.0.1'
correctness
This warning is likely to mean that your recipe will fail to run when you attempt to converge. Your recipe may be syntactically valid Ruby, but the attribute you have attempted to set on a built-in Chef resource is not recognised. This is commonly a typo or you need to check the documentation to see what the attribute you are trying to set is called:
This example matches the FC009 rule because punter
is not a
recognised attribute for the file resource.
Checking the documentation we can see the correct attribute is
owner
.
# Don't do this
file '/tmp/something' do
punter 'root'
group 'root'
mode '0755'
action :create
end
# Do this instead
file '/tmp/something' do
owner 'root'
group 'root'
mode '0755'
action :create
end
correctness
search
The search syntax used is not recognised as valid Lucene search criteria. This is commonly because you have made a typo or are not escaping special characters in the query syntax.
Note that this rule will not identify syntax errors in searches composed of subexpressions. It checks only for literal search strings.
This example matches the FC010 rule because search metacharacters - in this case the square brackets - have not been properly escaped.
With the characters escaped this will no longer match the rule.
# Don't do this
search(:node, 'run_list:recipe[foo::bar]') do |matching_node|
puts matching_node.to_s
end
# Do this instead
search(:node, 'run_list:recipe\[foo\:\:bar\]') do |matching_node|
puts matching_node.to_s
end
readme
supermarket
Supermarket will now render your cookbook README documentation inline - see this example for the mysql cookbook.
Your README needs to be in
Markdown format for
this to work. This rule will match any cookbook that does not have a
README.md
file in the root directory.
supermarket
readme
Deprecated. These haven’t existed since the very early days of Chef, and
the check for README.md files will catch what this rule used to.
Writing cookbook documentation in RDoc has been deprecated in favour of
Markdown format.
This rule will match any cookbook that has a README.rdoc
file in the
root directory.
portability
files
This warning means that you have hard-coded a file download path in your
cookbook to a temporary directory. This can be a problem on boxes built
with a small /tmp
mount point. Chef has its own configuration option
file_cache_path
you should use instead:
This example matches the FC013 rule because it hard-codes the download
path to /tmp
.
To remove this warning use the configured file_cache_path
:
# Don't do this
remote_file '/tmp/large-file.tar.gz' do
source 'http://www.example.org/large-file.tar.gz'
end
# Do this instead
remote_file "#{Chef::Config[:file_cache_path]}/large-file.tar.gz" do
source 'http://www.example.org/large-file.tar.gz'
end
style
libraries
Your cookbook has a fairly long ruby_block
resource. Long ruby_block
resources are often candidates for extraction to a separate module or
class under the libraries
directory.
style
definitions
Chef definitions are an older approach to creating a higher-level abstraction for a group of resources. Unlike Custom Resources they are not first class resources, cannot receive notifications, and do not support why-run mode. You should prefer Custom Resources for new development.
correctness
lwrp
This warning means that the LWRP does not declare a default action. You should normally define a default action on your resource to avoid confusing users. Most resources have an intuitive default action.
This example matches the FC016 rule because it does not declare a default action.
With a default action specified this warning will no longer be displayed.
# Don't do this
actions :create, :delete
# Do this instead
actions :create, :delete
default_action :create
This rule has been deprecated. Chef 13 now uses use_inline_resources by default so LWRPs always notify updates.
correctness
lwrp
deprecated
This example matches the FC018 rule because it uses the old syntax for indicating it has been updated.
This example uses the newer syntax and will not raise the warning.
# Don't do this
action :create do
# create action implementation
# My state has changed so I'd better notify observers, but I'm using
# a deprecated syntax
new_resource.updated = true
end
# Also don't do this
action :create do
# create action implementation
# My state has changed so I'd better notify observers, but I'm using
# a deprecated syntax
@updated = true
end
# Approach 1: Using converge_by
action :create do
converge_by("Creating my_resource #{new_resource.name}") do
# create action implementation
end
end
# Approach 2: Using use_inline_resources
use_inline_resources
action :create do
# create action implementation
end
style
attributes
Node attributes can be accessed in multiple ways in Chef. This warning is shown when a cookbook is not consistent in the approach it uses to access attributes. It is not displayed for variations between cookbooks.
# Don't do this
node[:apache][:dir] = '/etc/apache2'
directory node['apache']['dir'] do
owner 'apache'
group 'apache'
action :create
end
# Do this instead
node['apache']['dir'] = '/etc/apache2'
directory node['apache']['dir'] do
owner 'apache'
group 'apache'
action :create
end
This rule has been deprecated due to the frequency of false positives. See the discussion against issue #30 for more detail.
correctness
lwrp
A change introduced in Chef 0.10.6 means that conditions may not work as expected for resources redeclared with the same name. If your LWRP defines a resource and that resource:
Then you will likely find that only the first resource will be applied. See this ticket for more background:
Because the feed_pet
resource will have the same name across all
instances of your LWRP, the condition will only be checked for the
first resource.
By making the resource name change for each unique instance of our LWRP instance we avoid this behaviour.
# Don't do this
action :feed do
execute 'feed_pet' do
command "echo 'Feeding: #{new_resource.name}'; touch '/tmp/#{new_resource.name}'"
not_if { ::File.exists?("/tmp/#{new_resource.name}")}
end
end
# Do this instead
action :feed do
execute "feed_pet_#{new_resource.name}" do
command "echo 'Feeding: #{new_resource.name}'; touch '/tmp/#{new_resource.name}'"
not_if { ::File.exists?("/tmp/#{new_resource.name}")}
end
end
correctness
A change introduced in Chef 0.10.6 means that conditions may not work as expected for resources declared within a loop. If your recipe defines a resource and that resource:
Then you will likely find that only the first resource will be applied. See this ticket for more background:
Because the feed_pet resource will have the same name for every iteration of the loop, the condition will only be checked for the first resource.
By making the resource name change for each iteration of the loop we avoid this behaviour.
# Don't do this
%w(rover fido).each do |pet_name|
execute 'feed_pet' do
command "echo 'Feeding: #{pet_name}'; touch '/tmp/#{pet_name}'"
not_if { ::File.exists?("/tmp/#{pet_name}")}
end
end
# Do this instead
%w(rover fido).each do |pet_name|
execute "feed_pet_#{pet_name}" do
command "echo 'Feeding: #{pet_name}'; touch '/tmp/#{pet_name}'"
not_if { ::File.exists?("/tmp/#{pet_name}")}
end
end
This rule has been deprecated. While it’s often considered a more chef like coding style to use not_if and only_if within the resources, there are several downsides to this including the inclusion of the resources within resource collection and reporting.
portability
This warning is shown when:
If at all possible you should consider using platform_family
instead of
platform to ensure you support similar distros. Otherwise for the greatest
portability consider adding the missing platforms to your conditional.
This example matches the FC024 rule because it includes a case
statement that matches more than one flavour of a platform family
but omits other popular flavours from the same family.
This warning is no longer raised when the other common equivalent
RHEL-based distributions have been added to the when
.
# The RHEL platforms branch below omits popular distributions
case node[:platform]
when 'debian', 'ubuntu'
package 'foo' do
action :install
end
when 'centos', 'redhat'
package 'bar' do
action :install
end
end
case node[:platform]
when 'debian', 'ubuntu'
package 'foo' do
action :install
end
when 'centos', 'redhat', 'scientific', 'oracle'
package 'bar' do
action :install
end
end
correctness
deprecated
This warning is shown if:
* you have a cookbook that installs a Rubygem for use from Chef
* the cookbook uses the
compile-time gem install trick
which is deprecated from Chef 0.10.10 and is replaced by the first class
chef_gem
resource.
This example matches the FC025 rule because it uses the older approach for installing a gem so that it is available in the current run.
Use chef_gem
to install the gem to avoid this warning.
r = gem_package 'mysql' do
action :nothing
end
r.run_action(:install)
Gem.clear_paths
chef_gem 'mysql' do
compile_time true
end
correctness
This warning is shown if you have a conditional attribute declared on a resource as a block that contains only a single string.
This example matches the FC026 rule because it returns a string from the block. This will always evalute to true, and often indicates that you are trying to run a command rather than execute a Ruby block as your condition.
If the intention is to run the string as an operating system command then remove the block surrounding the command.
# Don't do this
template '/etc/foo' do
mode '0644'
source 'foo.erb'
not_if { 'test -f /etc/foo' }
end
# Do this instead
template '/etc/foo' do
mode '0644'
source 'foo.erb'
not_if 'test -f /etc/foo'
end
correctness
This warning is shown if you set an attribute on a Chef resource that is technically accessible but should not be set in normal usage. To avoid this warning allow Chef to set the value of the internal attribute rather than setting it yourself.
This example matches the FC027 rule because it sets the running
attribute on a service resource. This attribute should normally be
set by the provider itself and not in normal recipe usage.
In this particular example you can achieve the same effect by using
the service :start
action.
# Don't do this
service 'foo' do
running true
end
# Do this instead
service 'foo' do
action :start
end
correctness
This warning is shown if you attempt to use the platform?
Chef built-in
method as node.platform?
. Because of the way Chef attributes work the
later approach will not error but will do the wrong thing which may
result in resources you had intended to apply only to a single platform
instead being applied to all platforms.
This example matches the FC028 rule because the platform?
method
is incorrectly prefixed with node
.
Remove the leading node.
from the use of platform?
to resolve
this warning.
# Don't do this
file '/etc/foo' do
only_if { node.platform?('commodore64') }
end
# Do this instead
file '/etc/foo' do
only_if { platform?('commodore64') }
end
correctness
metadata
This warning is shown if you declare a recipe in your cookbook metadata without including the cookbook name as a prefix.
This example matches the FC029 rule because the metadata declares a recipe without prefixing it with the name of the current cookbook.
This modified example would not match the FC029 rule:
# Don't do this
name 'example'
version '1.2.3'
recipe 'default', 'Installs Example'
# Do this instead
name 'example'
version '1.2.3'
recipe 'example::default', 'Installs Example'
correctness
Pry is a fantastic tool for interactive exploration of a running Ruby program. You can place breakpoints in your cookbook code that will launch a Pry console. This warning is shown when your cookbook code contains these breakpoints, as failing to remove these will cause your Chef run to halt.
This rule currently only checks for use of binding.pry
and not the Chef
built-in breakpoint
resource which is never used outside of
chef-shell.
This example matches the FC030 rule because it includes a Pry
breakpoint declared with binding.pry
.
This modified example would not match the FC030 rule:
# Don't do this
template '/etc/foo' do
source 'foo.erb'
end
binding.pry
# Do this instead
template '/etc/foo' do
source 'foo.erb'
end
correctness
metadata
Chef cookbooks normally include a metadata.rb
file which can be used
to express a
wide range of metadata about a cookbook.
This warning is shown when a directory appears to contain a cookbook, but
does not include the expected metadata.rb
file at the top-level.
correctness
notifications
Chef notifications allow a resource to define that it should be actioned when another resource changes state.
Notification timing can be controlled and set to immediate
, or delayed
until the end of the Chef run. This warning is shown when the timing
specified is not recognised.
This example matches the FC032 rule because it specifies an invalid notification timing.
This modified example would not match the FC032 rule because the mispelt timing has been corrected.
# Don't do this
template '/etc/foo' do
notifies :restart, 'service[foo]', :imediately
end
# Do this instead
template '/etc/foo' do
notifies :restart, 'service[foo]', :immediate
end
correctness
templates
This warning is shown when the erb template associated with a template resource cannot be found.
correctness
templates
This warning is shown when one or more variables passed into a template by a template resource are not then used within the template.
This is often a sign that a template still contains hard-coded values that you intended to parameterise.
This example matches the FC034 rule because it passes two variables to the template, of which only the first is used.
This modified example would not match the FC034 rule becuse the template has been updated to include both variables passed through.
template '/etc/foo/config.conf' do
source 'config.conf.erb'
variables(
'config_var_a' => node['config']['config_var_a'],
'config_var_b' => node['config']['config_var_b']
)
end
# config.conf.erb
# var_a=<%= @config_var_a %>
template '/etc/foo/config.conf' do
source 'config.conf.erb'
variables(
'config_var_a' => node['config']['config_var_a'],
'config_var_b' => node['config']['config_var_b']
)
end
# config.conf.erb
# var_a=<%= @config_var_a %>
# var_b=<%= @config_var_b %>
This rule has been deprecated. See the discussion against issue #60 for more detail.
correctness
notifications
This warning is shown when a resource notifies another resource to take an action, but the action is invalid for the target resource type.
This example matches the FC037 rule because :activate_turbo_boost
is
not a valid action for services.
This modified example would not match the FC037 rule because the action has been corrected.
# Don't do this
template '/etc/foo.conf' do
notifies :activate_turbo_boost, 'service[foo]'
end
# Do this instead
template '/etc/foo.conf' do
notifies :restart, 'service[foo]'
end
correctness
This warning is shown when a resource action is not valid for the type of resource.
This example matches the FC038 rule because :none
is
not a valid action.
This modified example would not match the FC038 rule because the action has been corrected.
# Don't do this
service 'foo' do
action :none
end
# Do this instead
service 'foo' do
action :nothing
end
correctness
Chef allows you to use varying syntax to refer to node attributes.
This warning is shown when you attempt to reference a method on
Chef::Node
using the same string or symbol syntax reserved for node
attributes.
This example matches the FC039 rule because run_state
is
only accessible as a method and cannot be referenced as an attribute.
This modified example would not match the FC039 rule because the
run_state
is referenced as a method.
# Don't do this
node['run_state']['nginx_force_recompile'] = false
# Do this instead
node.run_state['nginx_force_recompile'] = false
style
This warning is shown if you declare an execute
resource that uses git.
If the command you are attempting to execute is supported by the git
resource you should probably use that instead.
This example matches the FC040 rule because an execute
resource is
used where you could instead use a git
resource.
This modified example would not match the FC040 rule because the
execute
resource has been replaced by a git
resource.
# Don't do this
execute 'git clone https://github.com/git/git.git' do
action :run
end
# Do this instead
git '/foo/bar' do
repository 'git://github.com/git/git.git'
reference 'master'
action :sync
end
style
portability
This warning is shown if you use an execute resource to run the curl
or
wget
commands. If you are downloading a file consider using the
remote_file
resource instead.
This example matches the FC041 rule because an execute
resource is
used where you could instead use a remote_file
resource.
This modified example would not match the FC041 rule because the
execute
resource has been replaced by a remote_file
resource.
# Don't do this
execute "cd /tmp && wget 'http://example.org/'" do
action :run
end
# Do this instead
remote_file '/tmp/testfile' do
source 'http://www.example.org/'
end
deprecated
correctness
This warning is shown when require_recipe
is used. Because
require_recipe
has been deprecated you should replace any references to
to require_recipe
with include_recipe
.
This example matches the FC042 rule because the deprecated
require_recipe
statement is used.
This modified example would not match the FC042 rule because the
require_recipe
statement has been replaced with include_recipe
.
# Don't do this
require_recipe 'apache2::default'
# Do this instead
include_recipe 'apache2::default'
correctness
notifications
deprecated
This warning is shown when you use the old-style notification syntax. You should prefer the new-style notification syntax which has the advantage that you can notify resources that are defined later.
This example matches the FC043 rule because it uses the older notification syntax.
This modified example would not match the FC043 rule because the syntax of the notification has been updated to use the new format.
# Don't do this
template '/etc/www/configures-apache.conf' do
notifies :restart, resources(:service => 'apache')
end
# Do this instead
template '/etc/www/configures-apache.conf' do
notifies :restart, 'service[apache]'
end
style
This warning is shown when, within a cookbook attributes file, you refer
to an attribute as you would a local variable rather than as an attribute
of the node
object. It is valid to do the former, but you should prefer
the later more explicit approach to accessing attributes because it is
easier for users of your cookbooks to understand.
This example matches the FC044 rule because it refers to the
hostname
attribute as a bare attribute.
This modified example would not match the FC044 rule because the
reference to the hostname
attribute has been qualified so that
the meaning is more apparent.
# Don't do this
default['myhostname'] = hostname
# Do this instead
default['myhostname'] = node['hostname']
correctness
metadata
chef12
This warning is shown when your cookbook does not define a name within
the cookbook metadata.rb
file. It’s a good idea to specify a name in
your cookbook metadata to avoid breakage if the name of the containing
directory changes. Additionally, Chef 12 requires the name to be included
in the metadata.rb file.
This example matches the FC045 because it lacks the name property
This modified example would not match the FC045 because it contains the name property
# Don't do this
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'All Rights Reserved'
description 'Installs/Configures test'
long_description 'Installs/Configures test'
version '0.1.0'
# Do this instead
name 'example'
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'All Rights Reserved'
description 'Installs/Configures test'
long_description 'Installs/Configures test'
version '0.1.0'
attributes
correctness
It is a
common convention in Ruby development
to use ||=
to assign a value to variable if it is false
or nil
.
Frequently developers with earlier exposure to Ruby attempt to use the
same approach to assign a default value to node attributes within Chef.
This doesn’t work correctly because Chef auto-vivifies attributes so a missing attribute is never falsey.
This example matches the FC046 rule because it uses assign unless nil
(||=
) with node attributes.
This modified example would not match the FC046 rule because the
assign unless nil expression has been replaced with default_unless
.
# Don't do this
default['somevalue'] ||= []
# Do this instead
default_unless['somevalue'] = []
attributes
correctness
chef11
From Chef 11 it is no longer possible to set attributes without specifying their precedence level. For more information refer to the list of Breaking Changes in Chef 11.
This example matches the FC047 rule because it writes to the attribute without specifying the precedence level to set.
This will work in Chef versions < 11 but you should prefer the new syntax.
This modified example would not match the FC047 rule because the
attribute assignment has been updated to specify a precedence level
of normal
.
# Don't do this
node['foo'] = 'bar'
# Do this instead
node.normal['foo'] = 'bar'
portability
Normally to execute an operating system command with Chef you would use
a built-in resource such as the execute
resource.
You might also have a need to spawn processes from Ruby, either inline
or within a ruby_block
. There are many different ways to do this in Ruby
- my favourite reference is
Jesse Storimer’s Working with Unix Processes.
Chef comes with a library called
Mixlib::ShellOut that
provides a more convenient interface and it is idiomatic to use it rather
than the backtick `
or %x{}
syntaxes.
This example matches the FC048 rule because it uses the %x{}
sigil.
This modified example would not match the FC048 rule because it is
using the Mixlib::ShellOut
library.
# Don't do this
result = %x{some_command}
raise 'Problem executing some_command' unless $?.success?
# Do this instead
cmd = Mixlib::ShellOut.new('some_command')
cmd.run_command
cmd.error!
style
roles
This warning is shown if you declare a name
in a
role file
that does not match the containing file name. Using the same name for both
is more consistent.
correctness
environments
roles
This warning is shown if the name declared in a role or environment file contains characters that are not allowed.
“[Names should be] made up of letters (upper-and lower-case), numbers, underscores, and hyphens:
[A-Z][a-z][0-9]
and [_-]
. Spaces are not allowed.”
This example matches the FC050 rule because the name includes a space character.
This modified example would not match the FC050 rule because the space has been removed from the role name.
# Don't do this
name 'web server'
run_list 'recipe[apache2]'
# Do this instead
name 'webserver'
run_list 'recipe[apache2]'
correctness
templates
This warning is shown if a template uses template partials in a way that would cause an infinite loop. For example if two template partials both include each other.
style
deprecated
metadata
This warning is shown if metadata.rb includes the suggests metadata. Suggests metadata was often used to inform users that a cookbook was required for a particular use case, but suggests itself was never implemented in chef-client. Adding suggests has no impact on the chef-client run and should be avoided.
# Don't do this
name 'example'
version '1.0.0'
suggests 'windows'
# Do this instead
name 'example'
version '1.0.0'
depends 'windows'
style
deprecated
metadata
This warning is shown if metadata.rb includes the recommends metadata. Recommends metadata was often used to inform users that a cookbook was recommended for a particular use case, but recommends itself was never implemented in chef-client. Adding recommends has no impact on the chef-client run and should be avoided.
# Don't do this
name 'example'
version '1.0.0'
recommends 'windows'
# Do this instead
name 'example'
version '1.0.0'
depends 'windows'
correctness
supermarket
metadata
This warning is shown if the metadata does not include the maintainer keyword. Cookbooks should always contain maintainer information so users can determine the maintainer of the cookbook.
correctness
supermarket
metadata
This warning is shown if the metadata does not include the maintainer_email keyword. Cookbooks should always contain maintainer_email so users can contact the maintainer.
This rule has been deprecated. Chef 13 now uses use_inline_resources by default so LWRPs always notify updates.
correctness
lwrp
This warning is shown if a library provider includes use_inline_resources,
but declares it’s actions using action_
This rule has been deprecated. Chef 13 now uses use_inline_resources by default so LWRPs always notify updates.
correctness
lwrp
This warning is shown if a LWRP provider includes use_inline_resources,
but declares it’s actions using action_
correctness
metadata
supermarket
This warning is shown if a cookbook includes an invalid version string in the metadata file. Cookbooks that do not follow this format cannot be uploaded to the chef server.
# Don't do this
name 'example'
version '1.0.0.1'
depends 'example'
# Do this instead
name 'example'
version '1.0.1'
metadata
supermarket
This warning is shown if a cookbook does not contain a version string in the metadata file. Without a version string cookbooks will be uploaded as version 0.0.0 each time. It is best practice to provide accurate versions that are incremented on each release, which requires specifying the string.
metadata
correctness
This warning is shown if a cookbook depends on itself within its own metadata. Cookbooks need specify a dependency on other cookbooks which they rely on, but all recipes, resources and libraries within the cookbook itself are loaded and available so there is noneed for a self dependency.
# Don't do this
name 'example'
version '1.0.0'
depends 'example'
# Do this instead
name 'example'
version '1.0.0'
metadata
supermarket
This warning is shown if a cookbook does not include the issues_url property in its metadata file. issues_url is used to point to the location for submitting issues (bugs) for the cookbook and is currently parsed by Supermarket to add links to community cookbooks. Note: issues_url requires Chef 12+.
# Don't do this
name 'example'
version '1.0.0'
# Do this instead
name 'example'
version '1.0.0'
issues_url 'https://github.com/chef-cookbooks/something/issues'
metadata
supermarket
This warning is shown if a cookbook does not include the source_url property in its metadata file. source_url is used to point to the source location for the cookbook and is currently parsed by Supermarket to add links to community cookbooks. Note: source_url requires Chef 12+.
name 'example'
version '1.0.0'
name 'example'
version '1.0.0'
source_url 'https://github.com/chef-cookbooks/something'
metadata
This warning is shown if a cookbook does not include the chef_version property in its metadata file. chef_version is used to clearly specify chef version compatibility to users and to chef-client.
name 'example'
version '1.0.0'
name 'example'
version '1.0.0'
chef_version '>= 12.5' if respond_to?(:chef_version)
metadata
supermarket
This warning is shown if a cookbook does not include any supports properties in its metadata file. supports is used to clearly specify platform support to users. Platform badges are added to cookbooks on Supermarket which allows users to search for specific platform supported cookbooks.
name 'example'
version '1.0.0'
name 'example'
version '1.0.0'
supports 'redhat'
metadata
supermarket
license
This warning is shown if a cookbook does not include a license property in its metadata file. license is used to clearly specify how the cookbook can be used, modified, and shared to users and is displayed on Supermarket.
name 'example'
version '1.0.0'
name 'example'
version '1.0.0'
license 'Apache-2.0'
metadata
supermarket
license
This warning is shown if a cookbook does not use a standardized SPDX.org defined license for the license property in its metadata file. Using a standardized license list enables users to identify valid compliant licenses.
name 'example'
version '1.0.0'
license 'Apache 2.0'
name 'example'
version '1.0.0'
license 'Apache-2.0'
metadata
supermarket
This warning is shown if a cookbook uses an invalid platform for a supports property in its metadata file. Using a valid platform enables users to identify supported cookbooks and ensures that searching on Supermarket with platforms specified returns the supported cookbooks.
name 'example'
version '1.0.0'
supports 'rhel'
name 'example'
version '1.0.0'
supports 'redhat'
style
license
This warning is shown if a cookbook does not include a LICENSE file. A LICENSE file allows consumers of cookbooks to determine if the terms allow them to use, change or distribute a cookbook. The file is also parsed by many many online services such as Github to provide addition functionality within their services.
metadata
style
This warning is shown if a cookbook defines its attributes in the metadata.rb file. Attributes defined in the metadata.rb file are not used by the chef-client or Supermarket and often become out of sync with the attributes files or readme. Documentation for attributes should instead be placed in the readme itself.
# Don't do this
name 'example'
version '1.0.0'
attribute 'something',
:display_name => 'Something',
:description => 'Hash of Something attributes',
:type => 'hash'
# Do this instead
name 'example'
version '1.0.0'
correctness
chef13
This warning is shown if a cookbook contains both a root alias and the target of the alias. Chef will ignore the non-alias file so it should be removed.
correctness
lwrp
Chef 11 introduced a new DSL method ‘default_action’ for LWRPs that allows defining the default action a LWRP should run if no action is specified. This method should be used instead of defining the default actoin through an initialize method in the resource.
# Don't do this
actions :add, :remove
def initialize(*args)
super
@action = :add
end
# Do this instead
actions :add, :remove
default_action :add
correctness
Chef provides a ‘node.save’ method, which allows saving the state of the node part way through a chef-client run. This is often used to ensure a run_list is saved or so that other state information is immediately available for search by other nodes in your environment. The use of node.save can be incredibly problematic and should be avoided as a run failure will still result in the node data being saved to the Chef server. If search is used to put nodes into production state this may result in non-functioning nodes being used.
style
deprecated
metadata
This warning is shown if metadata.rb includes the conflicts metadata. Conflicts metadata was often used to inform users of an incompatible cookbook that should not be used in conjunction with the current cookbook. Conflicts was never actually implemented in chef-client and its inclusion had no actual impact on the chef-client run.
# Don't do this
name 'example'
version '1.0.0'
conflicts 'foo'
# Do this instead
name 'example'
version '1.0.0'
style
deprecated
metadata
This warning is shown if metadata.rb includes the replaces metadata. Replaces metadata was often used to inform users of a previous cookbook that was replaced by the current cookbook. Replaces was never actually implemented in chef-client and its inclusion had no actual impact on the chef-client run.
# Don't do this
name 'example'
version '1.0.0'
replaces 'foo'
# Do this instead
name 'example'
version '1.0.0'
opensource
license
supermarket
This warning is shown if metadata.rb includes a cookbook license value that is not denoted as being an OSI approved open source license by SPDX.org.
deprecated
chef13
This warning is shown if a cookbook uses the legacy easy_install_package resource. This resource was deprecated in Chef 12 and removed in Chef 13.
deprecated
chef13
This warning is shown if a user resource includes the supports property, which was deprecated in Chef 12 and removed in Chef 13. See the example below for properly specificing values previously in supports
# Don't do this
user 'betty' do
action :create
supports({
manage_home: true,
non_unique: true
})
end
# Do this instead
user 'betty' do
action :create
manage_home true
non_unique true
end
chef12
This warning is shown if a cookbook metadata depends on the ‘partial_search’ cookbook. Chef 12 included the partial search functionality in chef-client itself so this cookbook is no longer necessary. See the Chef search filtering docs for usage of the built in functionality.
deprecated
chef14
This warning is shown if node.set or node.set_unless are used to set a value on the node. Both of these methods for setting attributes will be removed in Chef 14 as the names were confusing and particularly attractive to new users. These methods permanently set the attribute on the node even if the cookbook code is later removed, which is generally not what the user wants. If this functionality is in fact what you desire you should use node.normal or node.normal_unless, which are functionally equivalent. In general users should fully understand the implications of choosing a particular attribute level by reading the Chef attributes type documentation.
# Don't do this
node.set['foo']['bar'] = 'baz'
node.set_unless['foo1']['bar1'] = 'baz1'
# Do this instead if you actually want persistent attributes
node.normal['foo']['bar'] = 'baz'
node.normal_unless['foo1']['bar1'] = 'baz1'
deprecated
chef12
This warning is shown if an execute resource includes the deprecated path property, which was removed in Chef 12. You should instead using the environment property to set the PATH variable.
# Don't do this
execute 'some_binary some_option' do
path '/some/path/to/my/bin'
end
# Do this instead
execute 'some_binary some_option' do
environment 'PATH' => '/some/path/to/my/bin'
end
deprecated
chef13
This warning is shown if the deprecated Chef::REST class used in a cookbook. Chef::REST has been replaced by Chef::ServerAPI. See Chef Deprecation CHEF-9
correctness
This warning is shown if a LWRP or Custom Resource uses new_resource.updated_by_last_action(true) to signal that a resource has been updated, and thus any necessary notification should fire. This method of controlling resource state was necessary with Chef 10 and earlier, however it is no longer required when writing resources. Additionally updated_by_last_action often leads to resources notifying on every Chef run, regardless of actual change. By utilizing use_inline_resources it is no longer necessary to manually control resource state when resources are comprised of built-in Chef resources such as execute, file, directory, etc. For resources comprised of non-Chef Ruby code, such as API calls or Mixlib::ShellOut calls, resource state should be controlled with the converge_by helper. Converge_by wraps code that would make a change to the node, allowing for why-run mode and providing a friendly log message on convergence.
# Don't do this
action :create do
directory '/foo/bar' do
action :create
end
new_resource.updated_by_last_action(true)
end
# Do this instead
use_inline_resources
action :create do
directory '/foo/bar' do
action :create
end
end
# Don't do this
action :create do
create_something_api_call
new_resource.updated_by_last_action(true)
end
# Do do this
action :create do
converge_by "create something" do
create_something_api_call
end
end
style
This warning is shown if the data bag helper methods are not used to load data from a data bag. The data bag helpers are much simpler and also work for both encrypted and plain text data bags. See the Chef Data Bag Docs for additional usage details
# Don't do this
plain_text_data = Chef::DataBagItem.load('foo', 'bar')
encrypted_data = Chef::EncryptedDataBagItem.load('foo2', 'bar2')
# Do do this
plain_text_data = data_bag_item('foo', 'bar')
encrypted_data = data_bag_item('foo2', 'bar2')
deprecated
chef13
This warning is shown if the deprecated Chef::Platform.set method is used to define the platforms a HWRP runs on. This method has been removed from Chef 13. To create resources that map to specific platforms you should instead consider using provides in a custom resource. See the Chef Custom Resources Documention for additional details.
deprecated
chef13
This warning is shown if the deprecated Chef::Mixin::Command class is used to shell out within a recipe, library, or resource. This class has been removed in Chef 13 and Mixlib::Shellout should be used instead.
deprecated
chef13
This warning is shown if the deprecated Chef::ShellOut class is used to shell out within a recipe, library, or resource. This class has been removed in Chef 13 and Mixlib::ShellOut should be used instead.
# Don't do this
Chef::ShellOut.new('some_command').run_command
# Do this instead
Mixlib::ShellOut.new('some_command').run_command
correctness
This warning is shown if a custom resource defines attributes instead of properties. While Chef will do the right thing this may not always be the case and custom resources should be properly defined using properties.
# Don't do this
attribute :source, String, name_attribute: true
action :create do
# some resource code here
end
# Do this instead
property :source, String, name_property: true
action :create do
# some resource code here
end
correctness
This warning is shown if a custom resource declare its actions instead of letting Chef determine the set of actions defined in the resource itself.
# Don't do this
actions :create
action :create do
# some resource code here
end
# Do this instead
action :create do
# some resource code here
end
readme
supermarket
This warning is shown if you used chef generate cookbook
to create a new
cookbook and didn’t change boilerplate text in README file. You need to
update it with real description.
FC093 will match README files containing TODO: Enter the cookbook description here.
deprecated
chef14
This warning is shown if a cookbook uses the node[‘filesystem2’] attributes. In Chef 13 the filesystem Ohai plugin was replaced with the filesystem2 plugin. Data is written to both locations for now, but the existing node[‘filesystem2’] namespace will be removed in Chef 14 (April 2018). See https://docs.chef.io/deprecations_ohai_filesystem.html and https://docs.chef.io/deprecations_ohai_filesystem_v2.html.
# Don't do this
blocksize = node['filesystem2']['by_device']['/dev/disk1s1']['blocksize']
# Do this
blocksize = node['filesystem']['by_device']['/dev/disk1s1']['blocksize']
deprecated
chef14
This warning is shown if a cookbook uses the node[‘cloud_v2’] attributes. In Chef 13 the cloud Ohai plugin was replaced with the cloud_v2 plugin. Data is written to both locations for now, but the existing node[‘cloud_v2’] namespace will be removed in Chef 14 (April 2018). See https://docs.chef.io/deprecations_ohai_cloud.html and https://docs.chef.io/deprecations_ohai_cloud_v2.html.
# Don't do this
provider = node['cloud_v2']['provider']
# Do this
provider = node['cloud']['provider']
deprecated
chef14
This warning is shown if a cookbook uses the node[‘virtualization’] attributes populated by the libvirt Ohai plugin. This plugin polls data from libvirt, but requires installing an extra gem into the Chef installation, and therefore is not heavily used. In Chef 14 these attributes will be moved into their own namespace at node[‘libvirt’]. See https://docs.chef.io/deprecations_ohai_libvirt_plugin.html.
# Don't do this
uri = node['virtualzation']['uri']
# Do this
uri = node['libvirt']['uri']
deprecated
chef14
This warning is shown if a cookbook uses the Chef::Mixin::LanguageIncludeAttribute mixin. This mixin was deprecated with the release of Chef 11 and will be removed in Chef 14. Chef::DSL::IncludeAttribute should be used in its place.
# Don't do this
include Chef::Mixin::LanguageIncludeAttribute
# Do this
include Chef::DSL::IncludeAttribute
deprecated
chef14
This warning is shown if a cookbook uses the Chef::Mixin::RecipeDefinitionDSLCore mixin. This mixin was deprecated with the release of Chef 11 and will be removed in Chef 14. Chef::DSL::Recipe should be used in its place.
# Don't do this
include Chef::Mixin::RecipeDefinitionDSLCore
# Do this
include Chef::DSL::Recipe
deprecated
chef14
This warning is shown if a cookbook uses the Chef::Mixin::LanguageIncludeRecipe mixin. This mixin was deprecated with the release of Chef 11 and will be removed in Chef 14. Chef::DSL::IncludeRecipe should be used in its place.
# Don't do this
include Chef::Mixin::LanguageIncludeRecipe
# Do this
include Chef::DSL::IncludeRecipe
deprecated
chef14
This warning is shown if a cookbook uses the Chef::Mixin::Language mixin. This mixin was deprecated with the release of Chef 11 and will be removed in Chef 14. Chef::DSL::PlatformIntrospection or/and Chef::DSL::DataQuery should be used in its place.
# Don't do this
include Chef::Mixin::Language
# Use one or both of these
include Chef::DSL::PlatformIntrospection
include Chef::DSL::DataQuery
deprecated
chef14
This warning is shown if a cookbook uses the deploy resource. The deploy and deploy_revision resources have been deprecated as of Chef 13.6, and will be removed in Chef 14 (April 2018). See https://docs.chef.io/deprecations_deploy_resource.html.
deprecated
chef14
This warning is shown if a cookbook uses the Chef::DSL::Recipe::FullDSL Ruby module.
# Don't do this
include Chef::DSL::Recipe::FullDSL
# Use this instead
include Chef::DSL::Recipe
deprecated
chef14
This warning is shown if a cookbook includes a chocolatey_package resource using the :uninstall action. The :remove action should be used instead.
correctness
This warning is shown if a cookbook includes a ruby_block resource with the :create action or another resource notifies a ruby_block with the :create action. The :create action is an alias to :run and the :run action should be used instead as it is more clear what action Chef will be performing.
deprecated
chef14
This warning is shown if a cookbook uses the erl_call resource. The erl_call resource has been deprecated as of Chef 13.7, and will be removed in Chef 14 (April 2018). See https://docs.chef.io/deprecations_erl_call_resource.html.
deprecated
chef13
This warning is shown if a cookbook includes a launchd resource with a ‘hash’ property. In Chef 13.0 this property was renamed to plist_hash to avoid conflicts with Ruby itself.
deprecated
chef14
This warning is shown if a cookbook includes a resource with the ‘epic_fail’ property. The epic fail property is an alias to ‘ignore_failure’, which better describes the desired outcome. In Chef 14 (April 2018) epic_fail will be removed.
# Don't do this
execute 'some command' do
epic_fail true
end
# Do this instead
execute 'some command' do
ignore_failure true
end
correctness
This warning is shown if a resource defines a property with the name of ‘:name’. Chef itself creates this same name property by default, and it’s not necessary or desirable to define it again. This property can be removed from any resource. It should be noted that setting ‘name_property: true’ on properties with any other name is still entirely valid as that allows overriding the name specified when using the resource.
# Don't do this
property :name, String, name_property: true
property :foo, String
property :bar, String
# Do this instead
property :foo, String
property :bar, String
correctness
This warning is shown if a cookbook contains a package resource that defines its provider. If a specific package resource is needed for a package install that resource should be used instead of the package resource with a provider specified. The package resource wraps multiple platform specific platform specific package resources and dynamically uses the correct provider under the hood such as rpm_package or apt_package. Defining the provider outside of this logic will not always produce the intended results and may cause failures. It should also be noted that unless there is a specific reason for using a specific package resource you should always use ‘package’ and let Chef dynamically choose the right platform specific package resource at runtime.
# Don't do this
package 'foo' do
provider Chef::Provider::Package::Apt
action :install
end
# Do this instead
apt_package 'foo' do
action :install
end
deprecated
chef13
This warning is shown if a cookbook contains a script resource that defines the script in a ‘command’ property instead of a ‘code’ property
# Don't do this
script 'foo' do
command 'run some things'
end
# Do this instead
script 'foo' do
code 'run some things'
end
deprecated
chef13
This warning is shown if a cookbook uses search with the ‘sort’ flag. This flag hasn’t worked since Chef Server 9 and the flag was removed in Chef 13.
deprecated
chef13
This warning is shown if a cookbook contains a resource using the deprecated dsl_name method.
# Don't do this
my_resource = MyResource.dsl_name
# Do this instead
my_resource = MyResource.resource_name
deprecated
chef15
This warning is shown if a cookbook contains a resource using the deprecated use_inline_resources method. use_inline_resources is the default with Chef 13 and this call can be removed from all resources unless Chef 12 compatibility is needed.
deprecated
chef13
This warning is shown if a cookbook uses the legacy Ohai configuration syntax. This syntax needs to be used for Chef/Ohai 13. See https://docs.chef.io/deprecations_ohai_legacy_config.html for more information.
correctness
This warning is shown if a custom resource property has both required: true and name_property: true set. name_property: true instructs Chef to use the name of the resource unless the user has explicitly passed a value for the property. Since there is always a value for properties with name_property set there is no need to set required: true.
# Don't do this
property :my_property_name, String, name_property: true, required: true
# Do this instead
property :my_property_name, String, name_property: true
deprecated
This warning is shown if a cookbook depends on the now deprecated compat_resource cookbook. This cookbook backported newer Chef 12 functionality to older Chef 12 client releases. It was primarily used to provide custom resource fuctionality to 12.0-12.4 clients, but also backported several resources such as apt_repository and yum_repository. Chef 12 is end of life and this cookbook wasn’t necessary after Chef 12.19. Cookbooks should no longer rely on this cookbook, but should instead increase the minimal chef_version requirements in their metadata.
# Don't do this in metadata.rb
name 'my_cookbook'
depends 'compat_resource'
chef_version '>= 12.0'
# Do this instead in metadata.rb
name 'my_cookbook'
chef_version '>= 12.19'
correctness
This warning is shown if a custom resource property sets its type using kind_of. kind_of was used in LWRPs to set type in attributes, but should not be used in custom resources. Instead simply set the Ruby type for the property after the name as shown below.
# Don't do this
property :my_property_name, kind_of: String
# Do this instead
property :my_property_name, String
correctness
This warning is shown if a custom resource property sets name_attribute: true instead of name_property: true. This is generally found in LWRPs that were updated to custom resources as name_attribute was valid for LWRPs. They are currently aliases, but this may eventually cause failures.
# Don't do this
property :my_property_name, String, name_attribute: true
# Do this instead
property :my_property_name, String, name_property: true
chef13
deprecated
This warning is shown if a cookbook uses a windows_task resource with the action of :change. The original windows_task resource in the Windows cookbook required creating the task with the :create action and updating it with the :change action. In Chef 13 the windows_task shipped built into chef-client and was rewritten to properly update if necessary when using the :create action. Cookbooks using both :create and :change will need to be tested on Chef 13 using just the :create action.
correctness
A resource’s name should not be set via the name
property.
correctness
The build-essential
, dmg
, chef_handler
, chef_hostname
, mac_os_x
, swap
, or sysctl
cookbooks have been deprecated by built-in resources included with Chef 14. Removing these dependencies requires that metadata be changed to chef_version >= 14.0
.
deprecated
Chef 14 introduces a built-in resource, build_essential
, which deprecates the build-essential
cookbook. The cookbook has included this resource since v5.0.0.
files
Chef cookbooks should not be used to distribute binary files. This is better done via artifact stores such as Artifactory/Nexus or via a simple FTP/HTTP site.
Foodcritic comes with a bunch of rules built-in. You will probably find some of them useful and others annoying. The trick to only running the rules you actually care about are what foodcritic calls tags.
Each rule has a number of associated tags. You can filter which rules are actually checked by specifying the tags that you want to apply at the command line.
As an example, the following arguments will run foodcritic
but only showing warnings for rules tagged with the correctness
tag.
$ foodcritic -t correctness
Each rule is tagged with its own code, normally something like
FC123
. To avoid checking a particular rule use the
~
(tilde) modifier at the command line.
$ foodcritic -t ~FC002
Let's say we want to only check against rules that are tagged with
both style
and services
. We don't want to
check against rules that have only one or the other. Our command line to do
this would look like this:
$ foodcritic -t style -t services
Alternatively we might want to run rules that are tagged with either
style
or services
. To do this we separate the
rule codes with a comma:
$ foodcritic -t style,services
Below is the list of built-in foodcritic rules shown by tag:
Disabling certain tags is useful on the command line, but what if you need to disable a tag or a particular rule for just a single part of a recipe? Foodcritic allows you to disable individual rules or tags using a special code comment.
template 'my_awesome_template' do # ~FC033
source 'path/to/template'
end
Foodcritic tags can be enabled or disabled by including a .foodcritic
file at the root of your cookbook directory. Within this file you can use tags
or rules similar to how you would do on the command line.
To check rules with the style or services tag you would create a .foodcritic
file containing style,services
. For example:
$ echo "style,services" > my_cookbook/.foodcritic
To disable just a single rule such as FC016 create a .foodcritic file
containing ~FC016
. For example: $ echo "~FC016" > my_cookbook/.foodcritic
Awesome people have written additional rules that you can use with Foodcritic.
https://github.com/sous-chefs/sc-foodcritic-rules
https://github.com/customink-webops/foodcritic-rules
https://github.com/etsy/foodcritic-rules
https://github.com/lookout/lookout-foodcritic-rules
Find attributes accesses by type.
You might use this method to enforce local style rules on how attributes are accessed.
# All references to attributes using strings
# For example: node['foo']
attribute_access(ast, :type => :string)
# All references to attributes using symbols
# For example: node[:foo]
attribute_access(ast, :type => :symbol)
# All references to attributes using dots (vivified methods)
# For example: node.foo
attribute_access(ast, :type => :symbol)
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The AST of the cookbook recipe to check |
param | Hash |
options |
The options hash (see allowed values below) |
option | Symbol |
:type |
The approach used to access the attributes. One of |
option | Boolean |
:ignore_calls |
Exclude attribute accesses that mix strings/symbols with dot notation.
Defaults to |
return | Array |
The matching nodes if any |
The set of methods in the Chef DSL.
You can use this to see if a method reference is part of the Chef DSL or defined in a cookbook.
# Is search a method in the Chef DSL?
chef_dsl_methods.include?(:search)
=> true
category | type | name | description |
---|---|---|---|
return | Array |
Array of method symbols |
The name of the cookbook containing the specified file.
You can use this method in rules that need to work out if recipe code
refers to the current cookbook: for example when looking at
included_recipe
statements or LWRP usage.
cookbook_name('foo/recipes/default.rb')
=> "foo"
category | type | name | description |
---|---|---|---|
param | String |
file |
The file in the cookbook |
return | String |
The name of the containing cookbook |
The dependencies declared in cookbook metadata.
You can use this to check if all dependencies have been declared correctly or to find all cookbooks that share a common dependency.
ast = read_ast('postgresql/metadata.rb')
declared_dependencies(ast)
=> ["openssl"]
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The metadata rb AST |
return | Array |
List of cookbooks depended on |
The key / value pair in a ruby environment or role file.
# Retrieve the key and value of the 'name' field
field(ast, :name)
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The environment or role AST |
param | String |
field_name |
The name of the field to retrieve |
return | Nokogiri::XML::Node |
The matched key / value pair |
Retrieve the value from a ruby environment or role file.
# Retrieve the value of the 'name' field
field_value(ast, :name)
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The environment or role AST |
param | String |
field_name |
The name of the field to retrieve |
return | String |
The string value if specified as a literal. |
Create a match for a specified file. Use this if the presence of the file triggers the warning rather than content.
This is an alternative to match
where you don’t have a specific AST
element to associate the warning with. The call to file_match
will
typically be the last line in your rule.
file_match('foo/recipes/default.rb')
=> {:filename=>"foo/recipes/default.rb",
:matched=>"foo/recipes/default.rb",
:line=>1,
:column=>1}
category | type | name | description |
---|---|---|---|
param | String |
file |
The filename to create a match for |
return | Hash |
Hash with the match details |
Find Chef resources of the specified type.
Note that currently this method does not return blockless resources.
# Returns all resources in the AST
find_resources(ast)
# Returns just the packages
find_resources(ast, :type => :package)
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The AST of the cookbook recipe to check |
param | Hash |
options |
The options hash (see allowed values below) |
option | Symbol |
:type |
The type of resource to look for (or |
return | Array |
AST nodes of Chef resources. |
Retrieve the recipes that are included within the given recipe AST.
You can use this method to determine (and validate) recipe runtime dependencies.
# Find all include_recipe statements, discarding the AST nodes to just
# show the recipe names.
included_recipes(ast).keys
=> ["postgresql::client"]
included_recipes(ast, :with_partial_names => false).keys
=> ["postgresql::client"]
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The recipe AST |
param | Hash |
options |
|
return | Hash |
Hash keyed by included recipe name where the value is the AST node
of the |
Searches performed by the specified recipe that are literal strings. Searches with a query formed from a subexpression will be ignored.
ast = read_ast('zenoss/recipes/server.rb')
literal_searches(ast).size
=> 3
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The AST of the cookbook recipe to check |
return | Array |
The matching nodes |
Create a match from the specified node.
Return matches when a rule has matched against a recipe. A call to match
is typically the last line of your rule.
Ensure that the AST node you are passing to this method has a descendant
pos
node so that the match can be associated with a line in the file.
# You will frequently use map to apply the match function to an array of
# nodes that you consider matches for your rule.
attribute_access(ast, :type => :string).map{|s| match(s)}
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
node |
The node to create a match for |
return | Hash |
Hash with the matched node name and position with the recipe |
Provides convenient access to resource notification details. You can pass either the AST for an individual resource or the entire recipe to this method. Note that a resource may be registered for multiple notifications / subscriptions.
While Chef permits either :immediate
or :immediately
to be specified
in cookbooks, the timing for both will be returned as :immediate
to
remove the need for callers to switch on both values.
find_resources(ast).select do |resource|
notifications(resource).any? do |notification|
! [:delayed, :immediate].include? notification[:timing]
end
end
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The AST to check for notifications. |
return | Array |
A flat array of notification hashes.
|
Does the provided string look like an Operating System command? This is a rough heuristic to be taken with a pinch of salt.
category | type | name | description |
---|---|---|---|
param | String |
str |
The string to check |
return | Boolean |
True if this string might be an OS command |
Read the AST for the given Ruby or erb source file.
Many of the other functions documented here take an ast
as an argument.
You can also use Nokogiri’s support querying the AST with XPath or CSS
to implement your own rules.
# Normally the recipe AST will be passed in to your rule without you
# needing to use read_ast.
# However if you need to you can read in the AST for a cookbook recipe
# directly.
ast = read_ast('apache2/recipes/default.rb')
category | type | name | description |
---|---|---|---|
param | String |
file |
The file to read |
return | Nokogiri::XML::Node |
The recipe AST |
Determine if an action is valid for the given resource type.
resource_action?(:service, :restart)
=> true
category | type | name | description |
---|---|---|---|
param | Symbol |
resource_type |
The type of resource |
param | Symbol |
action |
The name of the action |
return | Boolean |
True if the action is valid for this type of resource. |
Retrieve a single-valued attribute from the specified resource.
# Given resource is a package
resource_attribute(resource, 'action')
=> :install
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
resource |
The resource AST to lookup the attribute under |
param | String |
name |
The attribute name |
return | String |
The attribute value for the specified attribute |
Is the specified attribute valid for the type of resource? Note that this
method will return true if the resource_type
is not recognised.
resource_attribute?(:file, :mode)
=> true
resource_attribute?(:file, :size)
=> false
# If the resource is not a Chef built-in then the attribute is always
# valid
resource_attribute?(:my_custom_resource, :whatever)
=> true
category | type | name | description |
---|---|---|---|
param | Symbol |
resource_type |
The type of Chef resource |
param | Symbol |
attribute_name |
The attribute name |
return | Boolean |
True if the attribute is valid for this type of resource |
Retrieve all attributes from the specified resource.
Use this method for convenient access to the resource attributes without needing to query the AST.
resource_attributes(resource)
=> {:name=>"zenoss", "arch"=>"kernel", "action"=>:install}
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
resource |
The resource AST |
return | Hash |
The resource attributes |
Retrieve the attributes as a hash for all resources of a given type.
Use this if you want to compare the attributes and values used by resources of the same type.
# The values of the Hash (ignored here) are arrays of resource ASTs.
resource_attributes_by_type(ast).keys.sort
=> ["apt_package",
"apt_repository",
"execute",
"package",
"ruby_block"]
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The recipe AST |
return | Hash |
Resources keyed by type, with an array for each |
Retrieve the name attribute associated with the specified resource.
resource_name(resource)
=> "zenoss"
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
resource |
The resource AST to lookup the name attribute under |
return | String |
The name attribute value |
Return the type, e.g. ‘package’ of a given resource.
You could use this if you wanted to take different action in your rule based on the resource type.
resource_type(resource)
=> "yum_package"
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
resource |
The resource AST |
return | String |
The type of resource |
Retrieve all resources of a given type.
The key of the hash is the type of resource (as a string). The value is an array of Hashes.
resources_by_type(ast).keys
=> ["yum_key",
"yum_repository",
"package",
"service",
"yum_package",
"apt_repository",
"apt_package"]
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The recipe AST |
return | Hash |
The matching resources |
Does the provided string look like ruby code? This does not evaluate the expression, instead only checking that it appears syntactically valid.
You can use this method to check that ruby_block
resources and recipes
themselves look like Ruby code.
# Lots of strings are well-formed Ruby statements, including some strings
# you might not expect:
ruby_code?('System.out.println("hello world");')
=> true
# This operating system command doesn't look like valid Ruby but others
# might.
ruby_code?('find -type f -print')
=> false
category | type | name | description |
---|---|---|---|
param | String |
str |
The string to check for rubiness |
return | Boolean |
|
Searches performed by the specified recipe.
In contrast to literal_searches
this method returns all searches.
You could use this method to identify all searches that search for a particular type of object, or to identify searches that are valid for a particular Chef version.
category | type | name | description |
---|---|---|---|
param | Nokogiri::XML::Node |
ast |
The AST of the cookbook recipe to check. |
return | Array |
The AST nodes in the recipe where searches are performed |
The list of standard cookbook sub-directories.
You can use this method when you need to traverse cookbooks manually yourself in order to determine directories to descend into.
standard_cookbook_subdirs
=> ["attributes",
"definitions",
"files",
"libraries",
"providers",
"recipes",
"resources",
"templates"]
category | type | name | description |
---|---|---|---|
return | Array |
The standard list of directories. |
List of templates that are included, including transitive includes.
templates_included(template_paths(filename), template_path)
category | type | name | description |
---|---|---|---|
param | Array |
all_templates |
The set of all templates |
param | String |
template_path |
The path to look under |
return | Array |
The set of included templates |
Is this a valid Lucene query?
Use this method when acting on searches in a recipe in order to check that they are valid before continuing with the rest of your rule.
valid_query?('run_list:recipe[foo::bar]')
=> false
valid_query?('run_list:recipe\[foo\:\:bar\]')
=> true
category | type | name | description |
---|---|---|---|
param | String |
query |
The query to check for syntax errors |
return | Boolean |
|