cookstyle 6.6.9 → 6.11.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/cookstyle.yml +66 -6
- data/config/disable_all.yml +18 -0
- data/config/upstream.yml +128 -23
- data/lib/cookstyle.rb +2 -1
- data/lib/cookstyle/version.rb +2 -2
- data/lib/rubocop/cop/chef/correctness/incorrect_library_injection.rb +10 -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 +3 -3
- 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/modernize/conditional_using_test.rb +56 -0
- data/lib/rubocop/cop/chef/modernize/includes_mixin_shellout.rb +24 -3
- data/lib/rubocop/cop/chef/modernize/node_init_package.rb +16 -8
- 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/cop/chef/style/include_recipe_with_parentheses.rb +57 -0
- data/lib/rubocop/monkey_patches/registry_cop.rb +14 -0
- data/lib/rubocop/monkey_patches/team.rb +24 -0
- metadata +13 -6
- data/lib/rubocop/cop/chef/deprecation/resource_without_name_or_provides.rb +0 -81
- data/lib/rubocop/monkey_patches/commissioner.rb +0 -26
data/lib/cookstyle.rb
CHANGED
@@ -11,7 +11,8 @@ require 'rubocop/monkey_patches/comment_config.rb'
|
|
11
11
|
# monkey patches needed for the TargetChefVersion config option
|
12
12
|
require 'rubocop/monkey_patches/config.rb'
|
13
13
|
require 'rubocop/monkey_patches/cop.rb'
|
14
|
-
require 'rubocop/monkey_patches/
|
14
|
+
require 'rubocop/monkey_patches/team.rb'
|
15
|
+
require 'rubocop/monkey_patches/registry_cop.rb'
|
15
16
|
|
16
17
|
module RuboCop
|
17
18
|
class ConfigLoader
|
data/lib/cookstyle/version.rb
CHANGED
@@ -25,6 +25,8 @@ module RuboCop
|
|
25
25
|
# # bad
|
26
26
|
# ::Chef::Recipe.send(:include, Filebeat::Helpers)
|
27
27
|
# ::Chef::Provider.send(:include, Filebeat::Helpers)
|
28
|
+
# ::Chef::Recipe.include Filebeat::Helpers
|
29
|
+
# ::Chef::Provider.include Filebeat::Helpers
|
28
30
|
#
|
29
31
|
# # good
|
30
32
|
# ::Chef::DSL::Recipe.send(:include, Filebeat::Helpers) # covers previous Recipe & Provider classes
|
@@ -36,10 +38,18 @@ module RuboCop
|
|
36
38
|
(send (const (const (cbase) :Chef) {:Recipe :Provider}) :send (sym :include) ... )
|
37
39
|
PATTERN
|
38
40
|
|
41
|
+
def_node_matcher :legacy_class_includes?, <<-PATTERN
|
42
|
+
(send (const (const (cbase) :Chef) {:Recipe :Provider}) :include ... )
|
43
|
+
PATTERN
|
44
|
+
|
39
45
|
def on_send(node)
|
40
46
|
legacy_class_sends?(node) do
|
41
47
|
add_offense(node, location: :expression, message: MSG, severity: :refactor)
|
42
48
|
end
|
49
|
+
|
50
|
+
legacy_class_includes?(node) do
|
51
|
+
add_offense(node, location: :expression, message: MSG, severity: :refactor)
|
52
|
+
end
|
43
53
|
end
|
44
54
|
|
45
55
|
def autocorrect(node)
|
@@ -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
|
@@ -19,7 +19,7 @@ module RuboCop
|
|
19
19
|
module Cop
|
20
20
|
module Chef
|
21
21
|
module ChefCorrectness
|
22
|
-
# When setting a node attribute as
|
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
23
|
#
|
24
24
|
# @example
|
25
25
|
#
|
@@ -32,10 +32,10 @@ module RuboCop
|
|
32
32
|
class LazyEvalNodeAttributeDefaults < Cop
|
33
33
|
include RuboCop::Chef::CookbookHelpers
|
34
34
|
|
35
|
-
MSG = 'When setting a node attribute as
|
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
36
|
|
37
37
|
def_node_matcher :non_lazy_node_attribute_default?, <<-PATTERN
|
38
|
-
|
38
|
+
(send nil? :property (sym _) ... (hash <(pair (sym :default) $(send (send _ :node) :[] _) ) ...>))
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def on_send(node)
|
@@ -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
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: 2019, 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 ChefModernize
|
21
|
+
# Use ::File.exist?('/foo/bar') instead of the slower 'test -f /foo/bar' which requires shelling out
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# only_if 'test -f /bin/foo'
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# only_if { ::File.exist?('bin/foo') }
|
30
|
+
#
|
31
|
+
class ConditionalUsingTest < Cop
|
32
|
+
MSG = "Use ::File.exist?('/foo/bar') instead of the slower 'test -f /foo/bar' which requires shelling out".freeze
|
33
|
+
|
34
|
+
def_node_matcher :resource_conditional?, <<~PATTERN
|
35
|
+
(send nil? {:not_if :only_if} $str )
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_send(node)
|
39
|
+
resource_conditional?(node) do |conditional|
|
40
|
+
add_offense(node, location: :expression, message: MSG, severity: :refactor) if conditional.value.match?(/^test -[ef] \S*$/)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def autocorrect(node)
|
45
|
+
lambda do |corrector|
|
46
|
+
resource_conditional?(node) do |conditional|
|
47
|
+
new_string = "{ ::File.exist?('#{conditional.value.match(/^test -[ef] (\S*)$/)[1]}') }"
|
48
|
+
corrector.replace(conditional.loc.expression, new_string)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
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
|
|
@@ -27,18 +27,20 @@ module RuboCop
|
|
27
27
|
# ::File.open('/proc/1/comm').chomp == 'systemd'
|
28
28
|
# File.open('/proc/1/comm').gets.chomp == 'systemd'
|
29
29
|
# File.open('/proc/1/comm').chomp == 'systemd'
|
30
|
-
# File.exist?('/proc/1/comm') && File.open('/proc/1/comm').chomp == 'systemd'
|
31
|
-
#
|
32
30
|
# IO.read('/proc/1/comm').chomp == 'systemd'
|
33
31
|
# IO.read('/proc/1/comm').gets.chomp == 'systemd'
|
34
32
|
# ::IO.read('/proc/1/comm').chomp == 'systemd'
|
35
33
|
# ::IO.read('/proc/1/comm').gets.chomp == 'systemd'
|
36
34
|
# File.exist?('/proc/1/comm') && File.open('/proc/1/comm').chomp == 'systemd'
|
35
|
+
# only_if 'test -f /bin/systemctl && /bin/systemctl'
|
37
36
|
#
|
38
37
|
# # good
|
39
38
|
# node['init_package'] == 'systemd'
|
39
|
+
# only_if { node['init_package'] == 'systemd' }
|
40
40
|
#
|
41
|
-
class NodeInitPackage <
|
41
|
+
class NodeInitPackage < Base
|
42
|
+
extend RuboCop::Cop::AutoCorrector
|
43
|
+
|
42
44
|
MSG = "Use node['init_package'] to check for systemd instead of reading the contents of '/proc/1/comm'".freeze
|
43
45
|
|
44
46
|
def_node_matcher :file_reads_proc_1_comm?, <<-PATTERN
|
@@ -58,18 +60,24 @@ module RuboCop
|
|
58
60
|
:== (str "systemd"))
|
59
61
|
PATTERN
|
60
62
|
|
63
|
+
def_node_matcher :file_systemd_conditional?, <<~PATTERN
|
64
|
+
(send nil? {:not_if :only_if} $(str "test -f /bin/systemctl && /bin/systemctl"))
|
65
|
+
PATTERN
|
66
|
+
|
61
67
|
def on_send(node)
|
62
68
|
compare_init_system?(node) do
|
63
69
|
# if there's a ::File.exist?('/proc/1/comm') check first we want to match that as well
|
64
70
|
node = node.parent if node.parent&.and_type? && proc_1_comm_exists?(node.parent.conditions.first)
|
65
71
|
|
66
|
-
add_offense(node
|
72
|
+
add_offense(node.loc.expression, message: MSG, severity: :refactor) do |corrector|
|
73
|
+
corrector.replace(node, "node['init_package'] == 'systemd'")
|
74
|
+
end
|
67
75
|
end
|
68
|
-
end
|
69
76
|
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
file_systemd_conditional?(node) do |conditional|
|
78
|
+
add_offense(node.loc.expression, message: MSG, severity: :refactor) do |corrector|
|
79
|
+
corrector.replace(conditional.loc.expression, "{ node['init_package'] == 'systemd' }")
|
80
|
+
end
|
73
81
|
end
|
74
82
|
end
|
75
83
|
end
|