cookstyle 6.5.3 → 6.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/config/cookstyle.yml +296 -12
- data/config/disable_all.yml +12 -0
- data/config/upstream.yml +82 -19
- data/lib/cookstyle.rb +2 -1
- data/lib/cookstyle/version.rb +2 -2
- data/lib/rubocop/chef/platform_helpers.rb +2 -1
- data/lib/rubocop/cop/chef/correctness/invalid_platform_family_values_in_case.rb +77 -0
- data/lib/rubocop/cop/chef/correctness/invalid_platform_values_in_case.rb +77 -0
- data/lib/rubocop/cop/chef/correctness/invalid_version_metadata.rb +1 -1
- data/lib/rubocop/cop/chef/correctness/lazy_eval_node_attribute_defaults.rb +56 -0
- data/lib/rubocop/cop/chef/correctness/openssl_password_helpers.rb +45 -0
- data/lib/rubocop/cop/chef/deprecation/hwrp_without_provides.rb +141 -0
- data/lib/rubocop/cop/chef/deprecation/resource_uses_only_resource_name.rb +86 -0
- data/lib/rubocop/cop/chef/deprecation/xml_ruby_recipe.rb +3 -3
- data/lib/rubocop/cop/chef/modernize/includes_mixin_shellout.rb +24 -3
- data/lib/rubocop/cop/chef/modernize/use_multipackage_installs.rb +8 -4
- data/lib/rubocop/cop/chef/redundant/multiple_platform_checks.rb +60 -0
- data/lib/rubocop/cop/chef/redundant/ohai_attribute_to_string.rb +68 -0
- data/lib/rubocop/cop/chef/sharing/include_resource_examples.rb +59 -0
- data/lib/rubocop/cop/chef/sharing/invalid_license_string.rb +1 -1
- data/lib/rubocop/monkey_patches/registry_cop.rb +14 -0
- data/lib/rubocop/monkey_patches/team.rb +24 -0
- metadata +15 -6
- data/lib/rubocop/cop/chef/deprecation/resource_without_name_or_provides.rb +0 -81
- data/lib/rubocop/monkey_patches/commissioner.rb +0 -26
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
|
37
37
|
def on_send(node)
|
38
38
|
version?(node) do |ver|
|
39
|
-
|
39
|
+
unless /\A\d+\.\d+(\.\d+)?\z/.match?(ver.value) # entirely borrowed from Foodcritic.
|
40
40
|
add_offense(ver, location: :expression, message: MSG, severity: :refactor)
|
41
41
|
end
|
42
42
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: 2020, Chef Software Inc.
|
3
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RuboCop
|
19
|
+
module Cop
|
20
|
+
module Chef
|
21
|
+
module ChefCorrectness
|
22
|
+
# When setting a node attribute as the default value for a custom resource property, wrap the node attribute in `lazy {}` so that its value is available when the resource executes.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# property :Something, String, default: node['hostname']
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# property :Something, String, default: lazy { node['hostname'] }
|
31
|
+
#
|
32
|
+
class LazyEvalNodeAttributeDefaults < Cop
|
33
|
+
include RuboCop::Chef::CookbookHelpers
|
34
|
+
|
35
|
+
MSG = 'When setting a node attribute as the default value for a custom resource property, wrap the node attribute in `lazy {}` so that its value is available when the resource executes.'.freeze
|
36
|
+
|
37
|
+
def_node_matcher :non_lazy_node_attribute_default?, <<-PATTERN
|
38
|
+
(send nil? :property (sym _) ... (hash <(pair (sym :default) $(send (send _ :node) :[] _) ) ...>))
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def on_send(node)
|
42
|
+
non_lazy_node_attribute_default?(node) do |default|
|
43
|
+
add_offense(default, location: :expression, message: MSG, severity: :refactor)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def autocorrect(node)
|
48
|
+
lambda do |corrector|
|
49
|
+
corrector.replace(node.loc.expression, "lazy { #{node.loc.expression.source} }")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Copyright:: Copyright 2020, Chef Software Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
module RuboCop
|
18
|
+
module Cop
|
19
|
+
module Chef
|
20
|
+
module ChefCorrectness
|
21
|
+
# The openSSL cookbook provides a deprecated `secure_password` helper in the `Opscode::OpenSSL::Password` class, which should not longer be used. This helper would generate a random password that would be used when a data bag or attribute was no present. The practice of generating passwords to be stored on the node is bad security as it exposes the password to anyone that can view the nodes, and deleting a node deletes the password. Passwords should be retrieved from a secure source for use in cookbooks.
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# ::Chef::Recipe.send(:include, Opscode::OpenSSL::Password)
|
25
|
+
# basic_auth_password = secure_password
|
26
|
+
#
|
27
|
+
class OpenSSLPasswordHelpers < Cop
|
28
|
+
MSG = 'The `secure_password` helper from the openssl cookbooks `Opscode::OpenSSL::Password` class should not be used to generate passwords.'.freeze
|
29
|
+
|
30
|
+
def_node_matcher :openssl_helper?, <<~PATTERN
|
31
|
+
(const
|
32
|
+
(const
|
33
|
+
(const nil? :Opscode) :OpenSSL) :Password)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_const(node)
|
37
|
+
openssl_helper?(node) do
|
38
|
+
add_offense(node, location: :expression, message: MSG, severity: :warning)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
3
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RuboCop
|
19
|
+
module Cop
|
20
|
+
module Chef
|
21
|
+
module ChefDeprecations
|
22
|
+
# Chef Infra Client 16 and later a legacy HWRP resource must use `provides` to define how the resource is called in recipes or other resources. To maintain compatibility with Chef Infra Client < 16 use both `resource_name` and `provides`.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# class Chef
|
28
|
+
# class Resource
|
29
|
+
# class UlimitRule < Chef::Resource
|
30
|
+
# property :type, [Symbol, String], required: true
|
31
|
+
# property :item, [Symbol, String], required: true
|
32
|
+
#
|
33
|
+
# # additional resource code
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # bad
|
39
|
+
# class Chef
|
40
|
+
# class Resource
|
41
|
+
# class UlimitRule < Chef::Resource
|
42
|
+
# resource_name :ulimit_rule
|
43
|
+
#
|
44
|
+
# property :type, [Symbol, String], required: true
|
45
|
+
# property :item, [Symbol, String], required: true
|
46
|
+
#
|
47
|
+
# # additional resource code
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # good when Chef Infra Client < 15 (but compatible with 16+ as well)
|
53
|
+
# class Chef
|
54
|
+
# class Resource
|
55
|
+
# class UlimitRule < Chef::Resource
|
56
|
+
# resource_name :ulimit_rule
|
57
|
+
# provides :ulimit_rule
|
58
|
+
#
|
59
|
+
# property :type, [Symbol, String], required: true
|
60
|
+
# property :item, [Symbol, String], required: true
|
61
|
+
#
|
62
|
+
# # additional resource code
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # good when Chef Infra Client 16+
|
68
|
+
# class Chef
|
69
|
+
# class Resource
|
70
|
+
# class UlimitRule < Chef::Resource
|
71
|
+
# provides :ulimit_rule
|
72
|
+
#
|
73
|
+
# property :type, [Symbol, String], required: true
|
74
|
+
# property :item, [Symbol, String], required: true
|
75
|
+
#
|
76
|
+
# # additional resource code
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# # better
|
82
|
+
# Convert your legacy HWRPs to custom resources
|
83
|
+
#
|
84
|
+
class HWRPWithoutProvides < Cop
|
85
|
+
MSG = 'In Chef Infra Client 16 and later a legacy HWRP resource must use `provides` to define how the resource is called in recipes or other resources. To maintain compatibility with Chef Infra Client < 16 use both `resource_name` and `provides`.'.freeze
|
86
|
+
|
87
|
+
def_node_matcher :HWRP?, <<-PATTERN
|
88
|
+
(class
|
89
|
+
(const nil? :Chef) nil?
|
90
|
+
(class
|
91
|
+
(const nil? :Resource) nil?
|
92
|
+
$(class
|
93
|
+
(const nil? ... )
|
94
|
+
(const
|
95
|
+
(const nil? :Chef) :Resource)
|
96
|
+
(begin ... ))))
|
97
|
+
PATTERN
|
98
|
+
|
99
|
+
def_node_search :provides, '(send nil? :provides (sym $_) ...)'
|
100
|
+
def_node_search :resource_name_ast, '$(send nil? :resource_name ...)'
|
101
|
+
def_node_search :resource_name, '(send nil? :resource_name (sym $_))'
|
102
|
+
|
103
|
+
def on_class(node)
|
104
|
+
HWRP?(node) do |inherit|
|
105
|
+
add_offense(inherit, location: :expression, message: MSG, severity: :warning) unless has_provides?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def has_provides?
|
110
|
+
provides_ast = provides(processed_source.ast)
|
111
|
+
return false if provides_ast.count == 0
|
112
|
+
|
113
|
+
resource_ast = resource_name(processed_source.ast)
|
114
|
+
|
115
|
+
if resource_ast.count == 0
|
116
|
+
true # no resource_name, but provides
|
117
|
+
else
|
118
|
+
# since we have a resource and provides make sure the there is a provides that
|
119
|
+
# matches the resource name
|
120
|
+
provides_ast.include?(resource_ast.first)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def indentation(node)
|
125
|
+
node.source_range.source_line =~ /\S/
|
126
|
+
end
|
127
|
+
|
128
|
+
def autocorrect(node)
|
129
|
+
lambda do |corrector|
|
130
|
+
resource_name_ast(node) do |ast_match|
|
131
|
+
# build a new string to add after that includes the new line and the proper indentation
|
132
|
+
new_string = "\n" + ast_match.source.dup.gsub('resource_name', 'provides').prepend(' ' * indentation(ast_match))
|
133
|
+
corrector.insert_after(ast_match.source_range, new_string)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
3
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
module RuboCop
|
18
|
+
module Cop
|
19
|
+
module Chef
|
20
|
+
module ChefDeprecations
|
21
|
+
# Starting with Chef Infra Client 16, using `resource_name` without also using `provides` will result in resource failures. Make sure to use both `resource_name` and `provides` to change the name of the resource. You can also omit `resource_name` entirely if the value set matches the name Chef Infra Client automatically assigns based on COOKBOOKNAME_FILENAME.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# mycookbook/resources/myresource.rb:
|
27
|
+
# resource_name :mycookbook_myresource
|
28
|
+
#
|
29
|
+
class ResourceUsesOnlyResourceName < Cop
|
30
|
+
include RuboCop::Chef::CookbookHelpers
|
31
|
+
include RangeHelp
|
32
|
+
|
33
|
+
MSG = 'Starting with Chef Infra Client 16, using `resource_name` without also using `provides` will result in resource failures. Make sure to use both `resource_name` and `provides` to change the name of the resource. You can also omit `resource_name` entirely if the value set matches the name Chef Infra Client automatically assigns based on COOKBOOKNAME_FILENAME.'.freeze
|
34
|
+
|
35
|
+
def_node_matcher :resource_name?, '(send nil? :resource_name (sym $_ ))'
|
36
|
+
|
37
|
+
def_node_search :cb_name_match, '(send nil? :name (str $_))'
|
38
|
+
|
39
|
+
def_node_search :provides, '(send nil? :provides (sym $_) ...)'
|
40
|
+
|
41
|
+
# determine the cookbook name either by parsing metdata.rb or by parsing metata.json
|
42
|
+
#
|
43
|
+
# @returns [String] the cookbook name
|
44
|
+
def cookbook_name
|
45
|
+
cb_path = File.expand_path(File.join(processed_source.file_path, '../..'))
|
46
|
+
|
47
|
+
if File.exist?(File.join(cb_path, 'metadata.rb'))
|
48
|
+
cb_metadata_ast = ProcessedSource.from_file(File.join(cb_path, 'metadata.rb'), @config.target_ruby_version).ast
|
49
|
+
cb_name_match(cb_metadata_ast).first
|
50
|
+
elsif File.exist?(File.join(cb_path, 'metadata.json')) # this exists only for supermarket files that lack metadata.rb
|
51
|
+
JSON.parse(File.read(File.join(cb_path, 'metadata.json')))['name']
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# given a resource name make sure there's a provides that matches that name
|
56
|
+
#
|
57
|
+
# @returns [TrueClass, FalseClass]
|
58
|
+
def valid_provides?(resource_name)
|
59
|
+
provides_ast = provides(processed_source.ast)
|
60
|
+
return false unless provides_ast
|
61
|
+
|
62
|
+
provides_ast.include?(resource_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_send(node)
|
66
|
+
resource_name?(node) do |r_name|
|
67
|
+
add_offense(node, location: :expression, message: MSG, severity: :warning) unless valid_provides?(r_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def autocorrect(node)
|
72
|
+
lambda do |corrector|
|
73
|
+
resource_name?(node) do |name|
|
74
|
+
if name.to_s == "#{cookbook_name}_#{File.basename(processed_source.path, '.rb')}"
|
75
|
+
corrector.remove(range_with_surrounding_space(range: node.loc.expression, side: :left))
|
76
|
+
else
|
77
|
+
corrector.insert_after(node.source_range, "\n#{node.source.gsub('resource_name', 'provides')}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright:: 2019, Chef Software, Inc.
|
2
|
+
# Copyright:: 2019-2020, Chef Software, Inc.
|
3
3
|
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -18,8 +18,7 @@ module RuboCop
|
|
18
18
|
module Cop
|
19
19
|
module Chef
|
20
20
|
module ChefDeprecations
|
21
|
-
# Do not include the deprecated xml::ruby recipe to install the nokogiri gem.
|
22
|
-
# Chef Infra Client 12 and later ships with nokogiri included.
|
21
|
+
# Do not include the deprecated xml::ruby recipe to install the nokogiri gem. Chef Infra Client 12 and later ships with nokogiri included.
|
23
22
|
#
|
24
23
|
# @example
|
25
24
|
#
|
@@ -35,6 +34,7 @@ module RuboCop
|
|
35
34
|
|
36
35
|
def on_send(node)
|
37
36
|
xml_ruby_recipe?(node) do
|
37
|
+
node = node.parent if node.parent&.conditional? && node.parent&.single_line_condition? # make sure we catch any inline conditionals
|
38
38
|
add_offense(node, location: :expression, message: MSG, severity: :warning)
|
39
39
|
end
|
40
40
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright:: 2019, Chef Software Inc.
|
2
|
+
# Copyright:: 2019-2020, Chef Software Inc.
|
3
3
|
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -42,13 +42,34 @@ module RuboCop
|
|
42
42
|
(send nil? :require ( str {"chef/mixin/shell_out" "chef/mixin/powershell_out"} ))
|
43
43
|
PATTERN
|
44
44
|
|
45
|
+
def_node_search :hwrp_classes?, <<-PATTERN
|
46
|
+
(class
|
47
|
+
(const ... )
|
48
|
+
{(const
|
49
|
+
(const
|
50
|
+
(const nil? :Chef) :Provider) :LWRPBase)
|
51
|
+
(const
|
52
|
+
(const nil? :Chef) :Provider)
|
53
|
+
}
|
54
|
+
...)
|
55
|
+
PATTERN
|
56
|
+
|
57
|
+
def check_for_offenses(node)
|
58
|
+
containing_dir = File.basename(File.dirname(processed_source.path))
|
59
|
+
|
60
|
+
# only add offenses when we're in a custom resource or HWRP, but not a plain old library
|
61
|
+
if containing_dir == 'resources' || hwrp_classes?(processed_source.ast)
|
62
|
+
add_offense(node, location: :expression, message: MSG, severity: :refactor)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
45
66
|
def on_send(node)
|
46
67
|
require_shellout?(node) do
|
47
|
-
|
68
|
+
check_for_offenses(node)
|
48
69
|
end
|
49
70
|
|
50
71
|
include_shellout?(node) do
|
51
|
-
|
72
|
+
check_for_offenses(node)
|
52
73
|
end
|
53
74
|
end
|
54
75
|
|
@@ -47,12 +47,14 @@ module RuboCop
|
|
47
47
|
(send
|
48
48
|
$(array ... ) :each)
|
49
49
|
(args ... )
|
50
|
-
(block
|
50
|
+
{(block
|
51
51
|
(send nil? :package
|
52
52
|
(lvar ... ))
|
53
53
|
(args)
|
54
54
|
(send nil? :action
|
55
|
-
(sym :install)))
|
55
|
+
(sym :install)))
|
56
|
+
(send nil? :package
|
57
|
+
(lvar _))}) nil?)
|
56
58
|
PATTERN
|
57
59
|
|
58
60
|
def_node_matcher :package_array_install?, <<-PATTERN
|
@@ -60,12 +62,14 @@ module RuboCop
|
|
60
62
|
(send
|
61
63
|
$(array ... ) :each)
|
62
64
|
(args ... )
|
63
|
-
(block
|
65
|
+
{(block
|
64
66
|
(send nil? :package
|
65
67
|
(lvar ... ))
|
66
68
|
(args)
|
67
69
|
(send nil? :action
|
68
|
-
(sym :install)))
|
70
|
+
(sym :install)))
|
71
|
+
(send nil? :package
|
72
|
+
(lvar _))})
|
69
73
|
PATTERN
|
70
74
|
|
71
75
|
# see if all platforms in the when condition are multipackage compliant
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: 2020, Chef Software, Inc.
|
3
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module RuboCop
|
19
|
+
module Cop
|
20
|
+
module Chef
|
21
|
+
module ChefRedundantCode
|
22
|
+
# You can pass multiple values to the platform? and platform_family? helpers instead of calling the helpers multiple times.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# platform?('redhat') || platform?('ubuntu')
|
28
|
+
# platform_family?('debian') || platform_family?('rhel')
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# platform?('redhat', 'ubuntu')
|
32
|
+
# platform_family?('debian', 'rhel')
|
33
|
+
#
|
34
|
+
class MultiplePlatformChecks < Cop
|
35
|
+
MSG = 'You can pass multiple values to the platform? and platform_family? helpers instead of calling the helpers multiple times.'.freeze
|
36
|
+
|
37
|
+
def_node_matcher :or_platform_helpers?, <<-PATTERN
|
38
|
+
(or (send nil? ${:platform? :platform_family?} $_ )* )
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def on_or(node)
|
42
|
+
or_platform_helpers?(node) do |helpers, _plats|
|
43
|
+
# if the helper types were the same it's an offense, but platform_family?('rhel') || platform?('ubuntu') is legit
|
44
|
+
add_offense(node, location: :expression, message: MSG, severity: :refactor) if helpers.uniq.size == 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def autocorrect(node)
|
49
|
+
or_platform_helpers?(node) do |type, plats|
|
50
|
+
lambda do |corrector|
|
51
|
+
new_string = "#{type.first}(#{plats.map(&:source).join(', ')})"
|
52
|
+
corrector.replace(node.loc.expression, new_string)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|