foodcritic 12.3.0 → 13.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/chef_dsl_metadata/{chef_12.21.14.json → chef_13.7.16.json} +1339 -1052
- data/features/step_definitions/cookbook_steps.rb +0 -18
- data/features/support/command_helpers.rb +0 -2
- data/foodcritic.gemspec +1 -1
- data/lib/foodcritic/chef.rb +2 -2
- data/lib/foodcritic/linter.rb +2 -2
- data/lib/foodcritic/notifications.rb +14 -3
- data/lib/foodcritic/rules/fc025.rb +3 -1
- data/lib/foodcritic/rules/fc026.rb +1 -1
- data/lib/foodcritic/rules/fc037.rb +2 -1
- data/lib/foodcritic/rules/fc044.rb +2 -2
- data/lib/foodcritic/rules/fc064.rb +1 -1
- data/lib/foodcritic/rules/fc065.rb +1 -1
- data/lib/foodcritic/rules/fc115.rb +9 -0
- data/lib/foodcritic/rules/fc117.rb +9 -0
- data/lib/foodcritic/rules/fc118.rb +7 -0
- data/lib/foodcritic/rules/fc119.rb +16 -0
- data/lib/foodcritic/template.rb +2 -2
- data/lib/foodcritic/version.rb +1 -1
- data/spec/functional/fc007_spec.rb +1 -1
- data/spec/functional/fc009_spec.rb +8 -13
- data/spec/functional/fc025_spec.rb +60 -0
- data/spec/functional/fc026_spec.rb +66 -0
- data/spec/functional/fc037_spec.rb +75 -0
- data/spec/functional/fc038_spec.rb +16 -11
- data/spec/functional/fc115_spec.rb +24 -0
- data/spec/functional/fc117_spec.rb +23 -0
- data/spec/functional/fc118_spec.rb +17 -0
- data/spec/functional/fc119_spec.rb +27 -0
- data/spec/regression/regression_spec.rb +2 -2
- data/spec/unit/linter_spec.rb +1 -1
- metadata +17 -14
- data/chef_dsl_metadata/chef_12.15.19.json +0 -18720
- data/chef_dsl_metadata/chef_12.16.42.json +0 -18848
- data/chef_dsl_metadata/chef_12.17.44.json +0 -19330
- data/chef_dsl_metadata/chef_12.18.31.json +0 -19738
- data/chef_dsl_metadata/chef_12.19.36.json +0 -20061
- data/chef_dsl_metadata/chef_12.20.3.json +0 -20067
- data/features/025_check_for_deprecated_gem_install.feature +0 -30
- data/features/026_check_for_conditional_block_string.feature +0 -20
@@ -409,20 +409,6 @@ Given 'a cookbook recipe that has a confusingly named local variable "default"'
|
|
409
409
|
}
|
410
410
|
end
|
411
411
|
|
412
|
-
Given /a cookbook recipe that (install|upgrade)s (a gem|multiple gems)(.*)$/ do |action, arity, approach|
|
413
|
-
if arity == "a gem"
|
414
|
-
if approach.empty?
|
415
|
-
recipe_installs_gem(:simple, action.to_sym)
|
416
|
-
else
|
417
|
-
recipe_installs_gem(:compile_time, action.to_sym)
|
418
|
-
end
|
419
|
-
elsif approach.include? "array"
|
420
|
-
recipe_installs_gem(:compile_time_from_array, action.to_sym)
|
421
|
-
else
|
422
|
-
recipe_installs_gem(:compile_time_from_word_list, action.to_sym)
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
412
|
Given "a cookbook recipe that refers to a hidden template" do
|
427
413
|
write_recipe %q{
|
428
414
|
template '/etc/.s3cfg' do
|
@@ -1779,10 +1765,6 @@ Then "the node access warning 001 should warn on lines 2 and 10 in that order" d
|
|
1779
1765
|
expect_output(expected_warnings.join("\n"))
|
1780
1766
|
end
|
1781
1767
|
|
1782
|
-
Then "the prefer chef_gem to manual install warning 025 should be shown" do
|
1783
|
-
expect_warning("FC025", :line => nil)
|
1784
|
-
end
|
1785
|
-
|
1786
1768
|
Then "the recipe filename should be displayed" do
|
1787
1769
|
expect_output "cookbooks/example/recipes/default.rb"
|
1788
1770
|
end
|
@@ -35,8 +35,6 @@ module FoodCritic
|
|
35
35
|
"FC021" => "Resource condition in provider may not behave as expected",
|
36
36
|
"FC022" => "Resource condition within loop may not behave as expected",
|
37
37
|
"FC024" => "Consider adding platform equivalents",
|
38
|
-
"FC025" => "Prefer chef_gem to compile-time gem install",
|
39
|
-
"FC026" => "Conditional execution block attribute contains only string",
|
40
38
|
"FC027" => "Resource sets internal attribute",
|
41
39
|
"FC028" => "Incorrect #platform? usage",
|
42
40
|
"FC029" => "No leading cookbook name in recipe metadata",
|
data/foodcritic.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.homepage = "http://foodcritic.io"
|
11
11
|
s.license = "MIT"
|
12
12
|
s.executables << "foodcritic"
|
13
|
-
s.required_ruby_version = ">= 2.
|
13
|
+
s.required_ruby_version = ">= 2.3"
|
14
14
|
|
15
15
|
s.files = Dir["chef_dsl_metadata/*.json"] +
|
16
16
|
Dir["lib/**/*.rb"] +
|
data/lib/foodcritic/chef.rb
CHANGED
@@ -52,8 +52,8 @@ module FoodCritic
|
|
52
52
|
Linter::DEFAULT_CHEF_VERSION
|
53
53
|
end
|
54
54
|
metadata_path = [version, version.sub(/\.[a-z].*/, ""),
|
55
|
-
Linter::DEFAULT_CHEF_VERSION].map do |
|
56
|
-
metadata_path(
|
55
|
+
Linter::DEFAULT_CHEF_VERSION].map do |ver|
|
56
|
+
metadata_path(ver)
|
57
57
|
end.find { |m| File.exist?(m) }
|
58
58
|
@dsl_metadata ||= FFI_Yajl::Parser.parse(IO.read(metadata_path),
|
59
59
|
symbolize_keys: true)
|
data/lib/foodcritic/linter.rb
CHANGED
@@ -9,7 +9,7 @@ module FoodCritic
|
|
9
9
|
|
10
10
|
# The default version that will be used to determine relevant rules. This
|
11
11
|
# can be over-ridden at the command line with the `--chef-version` option.
|
12
|
-
DEFAULT_CHEF_VERSION = "13.
|
12
|
+
DEFAULT_CHEF_VERSION = "13.7.16"
|
13
13
|
attr_reader :chef_version
|
14
14
|
|
15
15
|
# Perform a lint check. This method is intended for use by the command-line
|
@@ -285,7 +285,7 @@ module FoodCritic
|
|
285
285
|
if m.respond_to?(:node_name)
|
286
286
|
match(m)
|
287
287
|
elsif m.respond_to?(:xpath)
|
288
|
-
m.to_a.map { |
|
288
|
+
m.to_a.map { |n| match(n) }
|
289
289
|
else
|
290
290
|
m
|
291
291
|
end
|
@@ -126,10 +126,21 @@ module FoodCritic
|
|
126
126
|
resource_hash_references(notify).empty?
|
127
127
|
end
|
128
128
|
|
129
|
+
# return the notification action as either a symbol or string or nil if it's a variable.
|
130
|
+
# Yes you can notify an action as a string but it's wrong and we want to return it as
|
131
|
+
# a string so we can tell people not to do that.
|
129
132
|
def notification_action(notify)
|
130
|
-
notify.xpath(
|
131
|
-
|
132
|
-
|
133
|
+
is_variable = true unless notify.xpath("args_add_block/args_add//args_add[aref or vcall or call or var_ref]").empty?
|
134
|
+
string_val = notify.xpath("descendant::args_add/string_literal/string_add/tstring_content/@value").first
|
135
|
+
symbol_val = notify.xpath('descendant::args_add/args_add//symbol/ident/@value |
|
136
|
+
descendant::dyna_symbol[1]/xstring_add/tstring_content/@value').first
|
137
|
+
|
138
|
+
# 1) return a nil if the action is a variable like node['foo']['bar']
|
139
|
+
# 2) return the symbol if it exists
|
140
|
+
# 3) return the string since we're positive that we're not a symbol or variable
|
141
|
+
return nil if is_variable
|
142
|
+
return symbol_val.value.to_sym unless symbol_val.nil?
|
143
|
+
string_val.value
|
133
144
|
end
|
134
145
|
|
135
146
|
def notification_nodes(ast, &block)
|
@@ -1,8 +1,10 @@
|
|
1
1
|
rule "FC025", "Prefer chef_gem to compile-time gem install" do
|
2
2
|
tags %w{correctness deprecated}
|
3
3
|
recipe do |ast|
|
4
|
+
# when Ruby 2.4 support goes away this can be simplified to remove the
|
5
|
+
# do_block/stmts_add/command case which is Ruby 2.4
|
4
6
|
gem_install = ast.xpath("//stmts_add/assign[method_add_block[command/ident/
|
5
|
-
@value='gem_package'][do_block/stmts_add/command[ident/@value='action']
|
7
|
+
@value='gem_package'][do_block/bodystmt/stmts_add/command[ident/@value='action'] | do_block/stmts_add/command[ident/@value='action']
|
6
8
|
[descendant::ident/@value='nothing']]]")
|
7
9
|
gem_install.map do |install|
|
8
10
|
gem_var = install.xpath("var_field/ident/@value")
|
@@ -6,7 +6,7 @@ rule "FC026", "Conditional execution block attribute contains only string" do
|
|
6
6
|
end.flatten.compact.select do |condition|
|
7
7
|
condition.respond_to?(:xpath) &&
|
8
8
|
!condition.xpath("descendant::string_literal").empty? &&
|
9
|
-
!condition.xpath("stmts_add/string_literal").empty? &&
|
9
|
+
!condition.xpath("(stmts_add|bodystmt/stmts_add)/string_literal").empty? && # stmts_add can go away with Ruby 2.4
|
10
10
|
condition.xpath('descendant::stmts_add[count(ancestor::
|
11
11
|
string_literal) = 0]').size == 1
|
12
12
|
end
|
@@ -7,7 +7,8 @@ rule "FC037", "Invalid notification action" do
|
|
7
7
|
when :notifies then n[:resource_type]
|
8
8
|
when :subscribes then resource_type(resource).to_sym
|
9
9
|
end
|
10
|
-
|
10
|
+
# either the action is a string or it's not nil (means it was a variable) and not valid
|
11
|
+
n[:action].is_a?(String) || (!n[:action].nil? && !resource_action?(type, n[:action]))
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -9,8 +9,8 @@ rule "FC044", "Avoid bare attribute keys" do
|
|
9
9
|
[count(child::kw) = 0]/ident').select do |v|
|
10
10
|
|
11
11
|
local_declared = v.xpath("ancestor::*[self::brace_block or self::do_block]
|
12
|
-
/block_var/descendant::ident/@value").map do |
|
13
|
-
|
12
|
+
/block_var/descendant::ident/@value").map do |val|
|
13
|
+
val.to_s
|
14
14
|
end
|
15
15
|
|
16
16
|
(v["value"] != "secure_password") &&
|
@@ -0,0 +1,9 @@
|
|
1
|
+
rule "FC115", "Custom resource contains a name_property that is required" do
|
2
|
+
tags %w{correctness}
|
3
|
+
recipe do |ast|
|
4
|
+
ast.xpath("//command[ident/@value='property'
|
5
|
+
and descendant::bare_assoc_hash/assoc_new[label/@value='name_property:' and kw/@value='true']
|
6
|
+
and descendant::bare_assoc_hash/assoc_new[label/@value='required:' and kw/@value='true']
|
7
|
+
and descendant::symbol_literal/symbol/ident/@value!='name']")
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
rule "FC117", "Do not use kind_of in custom resource properties" do
|
2
|
+
tags %w{correctness}
|
3
|
+
resource do |ast|
|
4
|
+
# Make sure we're in a custom resource not an LWRP
|
5
|
+
if ast.xpath("//command/ident/@value='action'")
|
6
|
+
ast.xpath("//command[ident/@value='property'][args_add_block//label/@value='kind_of:']")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
rule "FC119", "windows_task :change action no longer exists in Chef 13" do
|
2
|
+
tags %w{deprecation chef13}
|
3
|
+
recipe do |ast|
|
4
|
+
matches = []
|
5
|
+
find_resources(ast).each do |resource|
|
6
|
+
# if it's a ruby_block check for the :create action
|
7
|
+
matches << resource if resource_attribute(resource, "action") == :change && resource_type(resource) == "windows_task"
|
8
|
+
|
9
|
+
# no matter what check notification
|
10
|
+
notifications(resource).any? do |notification|
|
11
|
+
matches << resource if notification[:resource_type] == :windows_task && notification[:action] == :change
|
12
|
+
end
|
13
|
+
end
|
14
|
+
matches
|
15
|
+
end
|
16
|
+
end
|
data/lib/foodcritic/template.rb
CHANGED
@@ -38,8 +38,8 @@ module FoodCritic
|
|
38
38
|
def expressions(template_code)
|
39
39
|
expr_lines = expressions_with_lines(template_code)
|
40
40
|
expr_lines.map do |expr, line|
|
41
|
-
|
42
|
-
{ code: expr, type:
|
41
|
+
ex = @expressions.find { |e| e[:code] == expr }
|
42
|
+
{ code: expr, type: ex[:type], line: line } if ex
|
43
43
|
end.compact
|
44
44
|
end
|
45
45
|
|
data/lib/foodcritic/version.rb
CHANGED
@@ -76,7 +76,7 @@ describe "FC007" do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
context "with an include from the same cookbook" do
|
79
|
-
recipe_file '
|
79
|
+
recipe_file 'include_recipe "test::other"'
|
80
80
|
it { is_expected.to_not violate_rule }
|
81
81
|
|
82
82
|
context "with the shorthand syntax" do
|
@@ -1,32 +1,27 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "FC009" do
|
4
|
-
context "on chef 13.
|
5
|
-
foodcritic_command("--chef-version", "13.
|
4
|
+
context "on chef 13.6.4 with a cookbook that new dsc_resource attributes" do
|
5
|
+
foodcritic_command("--chef-version", "13.6.4", "--no-progress", ".")
|
6
6
|
recipe_file <<-EOH
|
7
|
-
|
8
|
-
|
9
|
-
module_name 'foo'
|
10
|
-
module_version '1.0.0.0'
|
7
|
+
ifconfig 'foo' do
|
8
|
+
ethtool_opts 'something'
|
11
9
|
end
|
12
10
|
EOH
|
13
11
|
it { is_expected.not_to violate_rule }
|
14
12
|
end
|
15
13
|
|
16
|
-
context "on chef
|
17
|
-
foodcritic_command("--chef-version", "
|
14
|
+
context "on chef 13.0.113 with a cookbook that new dsc_resource attributes" do
|
15
|
+
foodcritic_command("--chef-version", "13.0.113", "--no-progress", ".")
|
18
16
|
recipe_file <<-EOH
|
19
|
-
|
20
|
-
|
21
|
-
module_name 'foo'
|
22
|
-
module_version '1.0.0.0'
|
17
|
+
ifconfig 'foo' do
|
18
|
+
ethtool_opts 'something'
|
23
19
|
end
|
24
20
|
EOH
|
25
21
|
it { is_expected.to violate_rule }
|
26
22
|
end
|
27
23
|
|
28
24
|
context "when the resource attribute is actually a raise" do
|
29
|
-
foodcritic_command("--chef-version", "12.18.31", "--no-progress", ".")
|
30
25
|
recipe_file <<-EOH
|
31
26
|
package package_name do
|
32
27
|
provider case node["platform_family"]
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "FC025" do
|
4
|
+
context "with a recipe that does a blockless gem_package install" do
|
5
|
+
recipe_file <<-EOH
|
6
|
+
gem_package 'foo'
|
7
|
+
EOH
|
8
|
+
it { is_expected.not_to violate_rule }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with a recipe that does a gem_package install" do
|
12
|
+
recipe_file <<-EOH
|
13
|
+
gem_package 'foo' do
|
14
|
+
action :install
|
15
|
+
EOH
|
16
|
+
it { is_expected.not_to violate_rule }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with a recipe that does a gem_package install with a nothing action" do
|
20
|
+
recipe_file <<-EOH
|
21
|
+
gem_package 'foo' do
|
22
|
+
action :nothing
|
23
|
+
EOH
|
24
|
+
it { is_expected.not_to violate_rule }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with a recipe that does a compile_time gem install from an array" do
|
28
|
+
recipe_file <<-EOH
|
29
|
+
%w{bencode i18n transmission-simple}.each do |pkg|
|
30
|
+
r = gem_package pkg do
|
31
|
+
action :nothing
|
32
|
+
end
|
33
|
+
r.run_action(:install)
|
34
|
+
end
|
35
|
+
EOH
|
36
|
+
it { is_expected.to violate_rule }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with a recipe that does a compile_time gem install" do
|
40
|
+
recipe_file <<-EOH
|
41
|
+
r = gem_package "activesupport" do
|
42
|
+
version '2.3.11'
|
43
|
+
action :nothing
|
44
|
+
end
|
45
|
+
r.run_action(:install)
|
46
|
+
EOH
|
47
|
+
it { is_expected.to violate_rule }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with a recipe that does a compile_time gem upgrade" do
|
51
|
+
recipe_file <<-EOH
|
52
|
+
r = gem_package "activesupport" do
|
53
|
+
version '2.3.11'
|
54
|
+
action :nothing
|
55
|
+
end
|
56
|
+
r.run_action(:upgrade)
|
57
|
+
EOH
|
58
|
+
it { is_expected.to violate_rule }
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "FC026" do
|
4
|
+
context "with a recipe that has a bracketed conditional that shouldn't be in a block" do
|
5
|
+
recipe_file <<-EOH
|
6
|
+
file 'foo' do
|
7
|
+
not_if { "ls foo" }
|
8
|
+
end
|
9
|
+
EOH
|
10
|
+
it { is_expected.to violate_rule }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with a recipe that has a conditional that shouldn't be in a block" do
|
14
|
+
recipe_file <<-EOH
|
15
|
+
file 'foo' do
|
16
|
+
not_if do "ls foo" end
|
17
|
+
end
|
18
|
+
EOH
|
19
|
+
it { is_expected.to violate_rule }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a recipe that has a conditional with a variable that shouldn't be in a block" do
|
23
|
+
recipe_file <<-EOH
|
24
|
+
file 'foo' do
|
25
|
+
only_if { "ls \#{node['foo']['path']}" }
|
26
|
+
end
|
27
|
+
EOH
|
28
|
+
it { is_expected.to violate_rule }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with a recipe that has a conditional with a method that shouldn't be in a block" do
|
32
|
+
recipe_file <<-EOH
|
33
|
+
file 'foo' do
|
34
|
+
not_if { "ls \#{foo.method()}" }
|
35
|
+
end
|
36
|
+
EOH
|
37
|
+
it { is_expected.to violate_rule }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with a recipe that has a conditional of foo.bar" do
|
41
|
+
recipe_file <<-EOH
|
42
|
+
file 'foo' do
|
43
|
+
only_if { foo.bar }
|
44
|
+
end
|
45
|
+
EOH
|
46
|
+
it { is_expected.not_to violate_rule }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with a recipe that has a conditional of foo.to_s" do
|
50
|
+
recipe_file <<-EOH
|
51
|
+
file 'foo' do
|
52
|
+
not_if { foo.to_s }
|
53
|
+
end
|
54
|
+
EOH
|
55
|
+
it { is_expected.not_to violate_rule }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with a recipe that has a conditional of File.exists?('/etc/foo')" do
|
59
|
+
recipe_file <<-EOH
|
60
|
+
file 'foo' do
|
61
|
+
not_if { File.exists?("/etc/foo") }
|
62
|
+
end
|
63
|
+
EOH
|
64
|
+
it { is_expected.not_to violate_rule }
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "FC037" do
|
4
|
+
context "with a resource that notifies using an action that is a string" do
|
5
|
+
recipe_file <<-EOF
|
6
|
+
file '/tmp/b.txt' do
|
7
|
+
content 'content'
|
8
|
+
notifies 'restart', 'service[httpd]', :delayed
|
9
|
+
end
|
10
|
+
EOF
|
11
|
+
it { is_expected.to violate_rule }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a resource that notifies using an action as a symbol" do
|
15
|
+
recipe_file <<-EOF
|
16
|
+
file '/tmp/a.txt' do
|
17
|
+
content 'content'
|
18
|
+
notifies :restart, 'service[httpd]', :delayed
|
19
|
+
end
|
20
|
+
EOF
|
21
|
+
it { is_expected.not_to violate_rule }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with a resource that notifies using an action as a :'symbol'" do
|
25
|
+
recipe_file <<-EOF
|
26
|
+
file '/tmp/a.txt' do
|
27
|
+
content 'content'
|
28
|
+
notifies :'restart', 'service[httpd]', :delayed
|
29
|
+
end
|
30
|
+
EOF
|
31
|
+
it { is_expected.not_to violate_rule }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with a resource that notifies using an action that is an attribute" do
|
35
|
+
recipe_file <<-EOF
|
36
|
+
file '/tmp/a.txt' do
|
37
|
+
content 'content'
|
38
|
+
notifies node['foo']['bar'], 'service[httpd]', :delayed
|
39
|
+
end
|
40
|
+
EOF
|
41
|
+
it { is_expected.not_to violate_rule }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a resource that notifies using an action that is a resource property" do
|
45
|
+
recipe_file <<-EOF
|
46
|
+
file '/tmp/a.txt' do
|
47
|
+
content 'content'
|
48
|
+
notifies new_resource.bob, 'service[httpd]', :delayed
|
49
|
+
end
|
50
|
+
EOF
|
51
|
+
it { is_expected.not_to violate_rule }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a resource that notifies using an action that is a variable" do
|
55
|
+
recipe_file <<-EOF
|
56
|
+
file '/tmp/a.txt' do
|
57
|
+
content 'content'
|
58
|
+
notifies foo, 'service[httpd]', :delayed
|
59
|
+
end
|
60
|
+
EOF
|
61
|
+
it { is_expected.not_to violate_rule }
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with a resource that notifies with a variable in a loop" do
|
65
|
+
recipe_file <<-EOF
|
66
|
+
file '/tmp/a.txt' do
|
67
|
+
content 'content'
|
68
|
+
Array(node['foo']['bar']).each do |action|
|
69
|
+
notifies action, 'service[httpd]', :delayed
|
70
|
+
end
|
71
|
+
end
|
72
|
+
EOF
|
73
|
+
it { is_expected.not_to violate_rule }
|
74
|
+
end
|
75
|
+
end
|