foodcritic 12.1.0 → 12.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/chef_dsl_metadata/chef_13.6.0.json +20328 -0
  4. data/lib/foodcritic/dsl.rb +1 -1
  5. data/lib/foodcritic/linter.rb +1 -1
  6. data/lib/foodcritic/rules/fc075.rb +1 -3
  7. data/lib/foodcritic/rules/fc082.rb +1 -3
  8. data/lib/foodcritic/rules/fc084.rb +1 -4
  9. data/lib/foodcritic/rules/fc085.rb +35 -2
  10. data/lib/foodcritic/rules/fc086.rb +2 -6
  11. data/lib/foodcritic/rules/fc087.rb +0 -1
  12. data/lib/foodcritic/rules/fc088.rb +1 -6
  13. data/lib/foodcritic/rules/fc089.rb +1 -6
  14. data/lib/foodcritic/rules/fc091.rb +0 -1
  15. data/lib/foodcritic/rules/fc092.rb +0 -1
  16. data/lib/foodcritic/rules/fc093.rb +0 -1
  17. data/lib/foodcritic/rules/fc094.rb +0 -1
  18. data/lib/foodcritic/rules/fc095.rb +0 -1
  19. data/lib/foodcritic/rules/fc096.rb +0 -1
  20. data/lib/foodcritic/rules/fc097.rb +1 -5
  21. data/lib/foodcritic/rules/fc098.rb +1 -5
  22. data/lib/foodcritic/rules/fc099.rb +1 -5
  23. data/lib/foodcritic/rules/fc100.rb +1 -5
  24. data/lib/foodcritic/rules/fc102.rb +1 -5
  25. data/lib/foodcritic/rules/fc103.rb +8 -0
  26. data/lib/foodcritic/rules/fc104.rb +18 -0
  27. data/lib/foodcritic/rules/fc105.rb +6 -0
  28. data/lib/foodcritic/rules/fc106.rb +8 -0
  29. data/lib/foodcritic/rules/fc107.rb +6 -0
  30. data/lib/foodcritic/rules/fc108.rb +12 -0
  31. data/lib/foodcritic/rules/fc109.rb +8 -0
  32. data/lib/foodcritic/version.rb +1 -1
  33. data/spec/functional/fc085_spec.rb +23 -4
  34. data/spec/functional/fc086_spec.rb +6 -2
  35. data/spec/functional/fc103_spec.rb +30 -0
  36. data/spec/functional/fc104_spec.rb +45 -0
  37. data/spec/functional/fc105_spec.rb +36 -0
  38. data/spec/functional/fc106_spec.rb +21 -0
  39. data/spec/functional/fc107_spec.rb +22 -0
  40. data/spec/functional/fc108_spec.rb +43 -0
  41. data/spec/functional/fc109_spec.rb +22 -0
  42. data/spec/regression/expected/database.txt +0 -1
  43. data/spec/unit/linter_spec.rb +1 -1
  44. metadata +18 -3
@@ -56,7 +56,7 @@ module FoodCritic
56
56
  end
57
57
 
58
58
  # The most frequently used block within a rule. A slight misnomer because
59
- # `recipe` rule blocks are also evaluated against providers.
59
+ # `recipe` rule blocks are also evaluated against resources, providers and libraries
60
60
  rule_block :recipe
61
61
 
62
62
  rule_block :cookbook
@@ -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.5.3"
12
+ DEFAULT_CHEF_VERSION = "13.6.0"
13
13
  attr_reader :chef_version
14
14
 
15
15
  # Perform a lint check. This method is intended for use by the command-line
@@ -1,9 +1,7 @@
1
1
  rule "FC075", "Cookbook uses node.save to save partial node data to the chef-server mid-run" do
2
2
  tags %w{correctness}
3
- def node_saves(ast)
3
+ recipe do |ast|
4
4
  ast.xpath('//call[(vcall|var_ref)/ident/@value="node"]
5
5
  [ident/@value="save"]')
6
6
  end
7
- recipe { |ast| node_saves(ast) }
8
- library { |ast| node_saves(ast) }
9
7
  end
@@ -1,9 +1,7 @@
1
1
  rule "FC082", "Deprecated node.set or node.set_unless used to set node attributes" do
2
2
  tags %w{chef14 deprecated}
3
- def node_sets(ast)
3
+ recipe do |ast|
4
4
  ast.xpath('//call[(vcall|var_ref)/ident/@value="node"]
5
5
  [ident[@value="set" or @value="set_unless"]]')
6
6
  end
7
- recipe { |ast| node_sets(ast) }
8
- library { |ast| node_sets(ast) }
9
7
  end
@@ -1,9 +1,6 @@
1
1
  rule "FC084", "Deprecated Chef::REST class used" do
2
2
  tags %w{chef13 deprecated}
3
- def rest(ast)
3
+ recipe do |ast|
4
4
  ast.xpath('//const_path_ref/const[@value="REST"]/..//const[@value="Chef"]/../../..')
5
5
  end
6
- recipe { |ast| rest(ast) }
7
- library { |ast| rest(ast) }
8
-
9
6
  end
@@ -1,8 +1,41 @@
1
1
  rule "FC085", "Resource using new_resource.updated_by_last_action to converge resource" do
2
2
  tags %w{chef13 deprecated}
3
3
  def updated_by(ast)
4
- ast.xpath('//call[(vcall|var_ref)/ident/@value="new_resource"]
5
- [ident/@value="updated_by_last_action"]')
4
+ # we need to handle both @new_resource.updated_by_last_action(true) or new_resource.updated_by_last_action(true)
5
+ # Here's the ast that xpath sees in all 3 possible scenarios from those two:
6
+ # <call value=".">
7
+ # <vcall value="vcall">
8
+ # <ident value="new_resource">
9
+ # <pos line="26" column="0"/>
10
+ # </ident>
11
+ # </vcall>
12
+ # <ident value="updated_by_last_action">
13
+ # <pos line="26" column="13"/>
14
+ # </ident>
15
+ # </call>
16
+ #
17
+ # <call value=".">
18
+ # <var_ref value="var_ref">
19
+ # <ivar value="@new_resource">
20
+ # <pos line="25" column="0"/>
21
+ # </ivar>
22
+ # </var_ref>
23
+ # <ident value="updated_by_last_action">
24
+ # <pos line="25" column="14"/>
25
+ # </ident>
26
+ # </call>
27
+ #
28
+ # <call value=".">
29
+ # <var_ref value="var_ref">
30
+ # <ident value="new_resource">
31
+ # <pos line="27" column="0"/>
32
+ # </ident>
33
+ # </vcall>
34
+ # <ident value="updated_by_last_action">
35
+ # <pos line="27" column="13"/>
36
+ # </ident>
37
+ # </call>
38
+ ast.xpath('descendant::*[self::var_ref/ident/@value="new_resource" or self::vcall/ident/@value="new_resource" or self::var_ref/ivar/@value="@new_resource"]/../ident[@value="updated_by_last_action"]')
6
39
  end
7
40
 
8
41
  resource { |ast| updated_by(ast) }
@@ -1,10 +1,6 @@
1
1
  rule "FC086", "Use databag helper methods to load data bag items" do
2
2
  tags %w{style}
3
- def old_dbag(ast)
4
- ast.xpath('//const_path_ref/const[@value="EncryptedDataBagItem" or @value="DataBagItem"]/..//const[@value="Chef"]/../../..//ident[@value!="load_secret"]/..')
3
+ recipe do |ast|
4
+ ast.xpath('//const_path_ref/const[@value="EncryptedDataBagItem" or @value="DataBagItem"]/..//const[@value="Chef"]/../../..//ident[@value="load"]/..')
5
5
  end
6
-
7
- resource { |ast| old_dbag(ast) }
8
- recipe { |ast| old_dbag(ast) }
9
- library { |ast| old_dbag(ast) }
10
6
  end
@@ -1,6 +1,5 @@
1
1
  rule "FC087", "Library uses deprecated Chef::Platform methods" do
2
2
  tags %w{chef13 deprecated}
3
-
4
3
  library do |ast|
5
4
  ast.xpath('//const_path_ref/const[@value="Platform"]/..//const[@value="Chef"]/../../../ident[@value="set" or @value="provider_for_resource" or @value="find_provider"]')
6
5
  end
@@ -1,11 +1,6 @@
1
1
  rule "FC088", "Prefer Mixlib::Shellout over deprecated Chef::Mixin::Command" do
2
2
  tags %w{chef13 deprecated}
3
-
4
- def includes_command(ast)
3
+ recipe do |ast|
5
4
  ast.xpath('//const_path_ref/const[@value="Command"]/..//const[@value="Mixin"]/..//const[@value="Chef"]')
6
5
  end
7
-
8
- resource { |ast| includes_command(ast) }
9
- recipe { |ast| includes_command(ast) }
10
- library { |ast| includes_command(ast) }
11
6
  end
@@ -1,11 +1,6 @@
1
1
  rule "FC089", "Prefer Mixlib::Shellout over deprecated Chef::ShellOut" do
2
2
  tags %w{chef13 deprecated}
3
-
4
- def old_shellout(ast)
3
+ recipe do |ast|
5
4
  ast.xpath('//const_path_ref[var_ref/const[@value="Chef"]]/const[@value="ShellOut"]')
6
5
  end
7
-
8
- resource { |ast| old_shellout(ast) }
9
- recipe { |ast| old_shellout(ast) }
10
- library { |ast| old_shellout(ast) }
11
6
  end
@@ -1,6 +1,5 @@
1
1
  rule "FC091", "Use property not attribute in custom resources" do
2
2
  tags %w{correctness}
3
-
4
3
  resource do |ast|
5
4
  # Make sure we're in a custom resource not an LWRP
6
5
  if ast.xpath("//command/ident/@value='action'")
@@ -1,6 +1,5 @@
1
1
  rule "FC092", "Custom resources should not define actions" do
2
2
  tags %w{correctness}
3
-
4
3
  resource do |ast|
5
4
  # Make sure we're in a custom resource not an LWRP
6
5
  if ast.xpath("//command/ident/@value='action'")
@@ -1,6 +1,5 @@
1
1
  rule "FC093", "Generated README text needs updating" do
2
2
  tags %w{readme supermarket}
3
-
4
3
  cookbook do |path|
5
4
  readme = File.join(path, "README.md")
6
5
  generated_readme = "TODO: Enter the cookbook description here."
@@ -1,6 +1,5 @@
1
1
  rule "FC094", "Cookbook uses deprecated filesystem2 ohai plugin data" do
2
2
  tags %w{deprecated chef14}
3
-
4
3
  recipe do |ast|
5
4
  ast.xpath('//aref[vcall/ident/@value="node"]
6
5
  /args_add_block/args_add/string_literal/string_add/tstring_content[@value="filesystem2"]')
@@ -1,6 +1,5 @@
1
1
  rule "FC095", "Cookbook uses deprecated cloud_v2 ohai plugin data" do
2
2
  tags %w{deprecated chef14}
3
-
4
3
  recipe do |ast|
5
4
  ast.xpath('//aref[vcall/ident/@value="node"]
6
5
  /args_add_block/args_add/string_literal/string_add/tstring_content[@value="cloud_v2"]')
@@ -1,6 +1,5 @@
1
1
  rule "FC096", "Cookbook uses deprecated libvirt virtualization ohai data" do
2
2
  tags %w{deprecated chef14}
3
-
4
3
  recipe do |ast|
5
4
  ast.xpath('//aref[aref/vcall/ident/@value="node"]
6
5
  [aref/args_add_block/args_add/string_literal/string_add/tstring_content/@value="virtualization" and
@@ -1,11 +1,7 @@
1
1
  rule "FC097", "Deprecated Chef::Mixin::LanguageIncludeAttribute mixin used" do
2
2
  tags %w{chef14 deprecated}
3
- def lang_include_attrib_mixin(ast)
3
+ recipe do |ast|
4
4
  # include Chef::Mixin::LanguageIncludeAttribute
5
5
  ast.xpath('//const_path_ref/const[@value="LanguageIncludeAttribute"]/..//const[@value="Mixin"]/..//const[@value="Chef"]')
6
6
  end
7
- recipe { |ast| lang_include_attrib_mixin(ast) }
8
- library { |ast| lang_include_attrib_mixin(ast) }
9
- resource { |ast| lang_include_attrib_mixin(ast) }
10
-
11
7
  end
@@ -1,11 +1,7 @@
1
1
  rule "FC098", "Deprecated Chef::Mixin::RecipeDefinitionDSLCore mixin used" do
2
2
  tags %w{chef14 deprecated}
3
- def recipe_def_mixin(ast)
3
+ recipe do |ast|
4
4
  # include Chef::Mixin::RecipeDefinitionDSLCore
5
5
  ast.xpath('//const_path_ref/const[@value="RecipeDefinitionDSLCore"]/..//const[@value="Mixin"]/..//const[@value="Chef"]')
6
6
  end
7
- recipe { |ast| recipe_def_mixin(ast) }
8
- library { |ast| recipe_def_mixin(ast) }
9
- resource { |ast| recipe_def_mixin(ast) }
10
-
11
7
  end
@@ -1,11 +1,7 @@
1
1
  rule "FC099", "Deprecated Chef::Mixin::LanguageIncludeRecipe mixin used" do
2
2
  tags %w{chef14 deprecated}
3
- def lang_include_mixin(ast)
3
+ recipe do |ast|
4
4
  # include Chef::Mixin::LanguageIncludeRecipe
5
5
  ast.xpath('//const_path_ref/const[@value="LanguageIncludeRecipe"]/..//const[@value="Mixin"]/..//const[@value="Chef"]')
6
6
  end
7
- recipe { |ast| lang_include_mixin(ast) }
8
- library { |ast| lang_include_mixin(ast) }
9
- resource { |ast| lang_include_mixin(ast) }
10
-
11
7
  end
@@ -1,11 +1,7 @@
1
1
  rule "FC100", "Deprecated Chef::Mixin::Language mixin used" do
2
2
  tags %w{chef14 deprecated}
3
- def lang_mixin(ast)
3
+ recipe do |ast|
4
4
  # include Chef::Mixin::Language
5
5
  ast.xpath('//const_path_ref/const[@value="Language"]/..//const[@value="Mixin"]/..//const[@value="Chef"]')
6
6
  end
7
- recipe { |ast| lang_mixin(ast) }
8
- library { |ast| lang_mixin(ast) }
9
- resource { |ast| lang_mixin(ast) }
10
-
11
7
  end
@@ -1,11 +1,7 @@
1
1
  rule "FC102", "Deprecated Chef::DSL::Recipe::FullDSL class used" do
2
2
  tags %w{chef14 deprecated}
3
- def full_dsl(ast)
3
+ recipe do |ast|
4
4
  # include Chef::DSL::Recipe::FullDSL
5
5
  ast.xpath('//const_path_ref/const[@value="FullDSL"]/..//const[@value="Recipe"]/..//const[@value="DSL"]/..//const[@value="Chef"]')
6
6
  end
7
- recipe { |ast| full_dsl(ast) }
8
- library { |ast| full_dsl(ast) }
9
- resource { |ast| full_dsl(ast) }
10
-
11
7
  end
@@ -0,0 +1,8 @@
1
+ rule "FC103", "Deprecated :uninstall action in chocolatey_package used" do
2
+ tags %w{deprecated chef14}
3
+ recipe do |ast|
4
+ find_resources(ast, type: "chocolatey_package").find_all do |choco_resource|
5
+ resource_attribute(choco_resource, "action") == :uninstall
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ rule "FC104", "Use the :run action in ruby_block instead of :create" do
2
+ tags %w{correctness}
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
+ if ast.xpath('//method_add_block[command/ident[@value="ruby_block"]]')
8
+ matches << resource if resource_attribute(resource, "action") == :create
9
+ end
10
+
11
+ # no matter what check notification
12
+ notifications(resource).any? do |notification|
13
+ matches << resource if notification[:resource_type] == :ruby_block && notification[:action] == :create
14
+ end
15
+ end
16
+ matches
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ rule "FC105", "Deprecated erl_call resource used" do
2
+ tags %w{chef14 deprecated}
3
+ recipe do |ast|
4
+ find_resources(ast, type: "erl_call")
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ rule "FC106", "Use the plist_hash property in launchd instead of hash" do
2
+ tags %w{deprecation chef13}
3
+ recipe do |ast|
4
+ find_resources(ast, type: "launchd").find_all do |launchd_resource|
5
+ resource_attribute(launchd_resource, "hash")
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ rule "FC107", "Resource uses epic_fail instead of ignore_failure" do
2
+ tags %w{deprecated chef14}
3
+ recipe do |ast|
4
+ find_resources(ast).xpath('(.//command|.//fcall)[ident/@value="epic_fail"]')
5
+ end
6
+ end
@@ -0,0 +1,12 @@
1
+ rule "FC108", "Resource should not define a property named 'name'" 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
+ # command has a child of type ident with a value of "property". That tells us
7
+ # we're in a property. Quite a ways desecendant from that is another ident
8
+ # with value of "name"
9
+ ast.xpath("//command[ident/@value='property' and descendant::symbol_literal/symbol/ident/@value='name']")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ rule "FC109", "Use platform-specific package resources instead of provider property" do
2
+ tags %w{correctness}
3
+ recipe do |ast|
4
+ find_resources(ast, type: "package").find_all do |package_resources|
5
+ resource_attribute(package_resources, "provider")
6
+ end
7
+ end
8
+ end
@@ -1,4 +1,4 @@
1
1
  module FoodCritic
2
2
  # The current version of foodcritic
3
- VERSION = "12.1.0"
3
+ VERSION = "12.2.0"
4
4
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "FC085" do
4
- context "with a cookbook with a custom resource that converges with updated_by_last_action" do
4
+ context "with a cookbook with a custom resource that converges with new_resource.updated_by_last_action" do
5
5
  resource_file <<-EOF
6
6
  action :create do
7
7
  template "/etc/something.conf" do
@@ -14,8 +14,8 @@ describe "FC085" do
14
14
  it { is_expected.to violate_rule }
15
15
  end
16
16
 
17
- context "with a cookbook with a LWRP that converges with updated_by_last_action" do
18
- resource_file <<-EOF
17
+ context "with a cookbook with a LWRP that converges with @new_resource.updated_by_last_action" do
18
+ provider_file <<-EOF
19
19
  use_inline_resources
20
20
 
21
21
  action :create do
@@ -23,6 +23,15 @@ describe "FC085" do
23
23
  notifies :restart, "service[something]"
24
24
  end
25
25
 
26
+ @new_resource.updated_by_last_action(true)
27
+ end
28
+ EOF
29
+ it { is_expected.to violate_rule }
30
+ end
31
+
32
+ context "with a cookbook with a LWRP that converges with new_resource.updated_by_last_action in a method" do
33
+ provider_file <<-EOF
34
+ def update_me(new_resource)
26
35
  new_resource.updated_by_last_action(true)
27
36
  end
28
37
  EOF
@@ -42,7 +51,7 @@ describe "FC085" do
42
51
  end
43
52
 
44
53
  context "with a cookbook with a LWRP that relies on resources for convergence" do
45
- resource_file <<-EOF
54
+ provider_file <<-EOF
46
55
  use_inline_resources
47
56
 
48
57
  action :create do
@@ -55,4 +64,14 @@ describe "FC085" do
55
64
  it { is_expected.to_not violate_rule }
56
65
  end
57
66
 
67
+ context "with a cookbook with a LWRP that calls foo.updated_by_last_action" do
68
+ provider_file <<-EOF
69
+ use_inline_resources
70
+
71
+ action :create do
72
+ foo.updated_by_last_action(true)
73
+ EOF
74
+ it { is_expected.to_not violate_rule }
75
+ end
76
+
58
77
  end
@@ -34,8 +34,12 @@ describe "FC086" do
34
34
  it { is_expected.not_to violate_rule }
35
35
  end
36
36
 
37
- context "with a recipe that uses Chef::EncryptedDataBagItem.load_secret" do
38
- recipe_file "data_bag_item('bag', 'item', Chef::EncryptedDataBagItem.load_secret('secret_file'))"
37
+ context "with a recipe that uses other Chef::EncryptedDataBagItem methods" do
38
+ recipe_file <<-EOF
39
+ data_bag_item('bag', 'item', Chef::EncryptedDataBagItem.load_secret('secret_file'))
40
+ encrypted_item = Chef::EncryptedDataBagItem.encrypt_data_bag_item(original_item, Chef::EncryptedDataBagItem.load_secret)
41
+ bag = Chef::DataBagItem.new
42
+ EOF
39
43
  it { is_expected.not_to violate_rule }
40
44
  end
41
45
  end
@@ -0,0 +1,30 @@
1
+ require "spec_helper"
2
+
3
+ describe "FC103" do
4
+ context "with a cookbook with a custom resource that uses the :uninstall resource in chocolatey_package" do
5
+ resource_file <<-EOF
6
+ chocolatey_package 'name' do
7
+ action :uninstall
8
+ end
9
+ EOF
10
+ it { is_expected.to violate_rule }
11
+ end
12
+
13
+ context "with a cookbook with a recipe that uses the :uninstall resource in chocolatey_package" do
14
+ recipe_file <<-EOF
15
+ chocolatey_package 'name' do
16
+ action :uninstall
17
+ end
18
+ EOF
19
+ it { is_expected.to violate_rule }
20
+ end
21
+
22
+ context "with a cookbook with a library that uses the :uninstall resource in chocolatey_package" do
23
+ library_file <<-EOF
24
+ chocolatey_package 'name' do
25
+ action :uninstall
26
+ end
27
+ EOF
28
+ it { is_expected.to violate_rule }
29
+ end
30
+ end