Class: RuboCop::Cop::Chef::Correctness::EmptyResourceGuard

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/chef/correctness/empty_resource_guard.rb

Overview

Resource guards (not_if/only_if) should not be empty. An empty string always evaluates to true and an empty block always evaluates to false, so in either case the guard stops doing the job it was written for and the resource silently runs, or fails to run, on every converge.

Empty strings in Ruby are "truthy", which means:

  • only_if '' will ALWAYS execute the resource (guard always passes)
  • not_if '' will NEVER execute the resource (guard always blocks)

An empty block behaves the other way around, since a block with no body returns nil:

  • only_if { } will NEVER execute the resource
  • not_if { } will ALWAYS execute the resource

This behavior is usually unintended and can lead to resources running when they shouldn't or never running when they should.

Examples:


# bad
template '/etc/foo' do
  mode '0644'
  source 'foo.erb'
  only_if ''  # This will always be true - resource always executes
end

cookbook_file '/logs/foo/error.log' do
  source 'error.log'
  not_if { '' }  # This will always be true - resource never executes
end

service 'apache2' do
  action :restart
  only_if { '' }  # Block form also problematic
end

# good
template '/etc/foo' do
  mode '0644'
  source 'foo.erb'
  only_if 'test -f /etc/foo'  # Actual shell command
end

cookbook_file '/logs/foo/error.log' do
  source 'error.log'
  not_if { ::File.exist?('/logs/foo/error.log') }  # Proper Ruby expression
end

service 'apache2' do
  action :restart
  only_if { node['platform'] == 'ubuntu' }  # Meaningful condition
end

# Or simply remove the guard if no condition is needed
package 'curl' do
  action :install
end

Constant Summary collapse

MSG =
'Resource guards (not_if/only_if) should not be empty strings as empty strings will always evaluate to true.'
EMPTY_BLOCK_MSG =
'Resource guards (not_if/only_if) should not be empty blocks as an empty block returns nil, which always evaluates to false.'
RESTRICT_ON_SEND =
[:not_if, :only_if].freeze

Instance Method Summary collapse

Methods inherited from Base

#target_chef_version

Instance Method Details

#empty_string?(str) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/rubocop/cop/chef/correctness/empty_resource_guard.rb', line 97

def empty_string?(str)
  str.empty?
end

#on_block(node) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/rubocop/cop/chef/correctness/empty_resource_guard.rb', line 107

def on_block(node)
  empty_string_block_guard?(node) do
    add_offense(node, severity: :refactor)
  end

  empty_block_guard?(node) do
    add_offense(node, message: EMPTY_BLOCK_MSG, severity: :refactor)
  end
end

#on_send(node) ⇒ Object



101
102
103
104
105
# File 'lib/rubocop/cop/chef/correctness/empty_resource_guard.rb', line 101

def on_send(node)
  empty_string_guard?(node) do
    add_offense(node, severity: :refactor)
  end
end