cookstyle 8.7.6 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/chefstyle.yml +2 -0
- data/config/cookstyle.yml +145 -6
- data/lib/cookstyle/version.rb +2 -2
- data/lib/rubocop/chef/cookbook_helpers.rb +23 -0
- data/lib/rubocop/chef.rb +1 -1
- data/lib/rubocop/cop/chef/correctness/chef_application_fatal.rb +16 -4
- data/lib/rubocop/cop/chef/correctness/conditional_unified_mode_true.rb +91 -0
- data/lib/rubocop/cop/chef/correctness/empty_resource_guard.rb +18 -2
- data/lib/rubocop/cop/chef/correctness/execute_delete_file.rb +127 -0
- data/lib/rubocop/cop/chef/correctness/invalid_checksum.rb +79 -0
- data/lib/rubocop/cop/chef/correctness/invalid_platform_family_helper.rb +1 -1
- data/lib/rubocop/cop/chef/correctness/invalid_platform_family_values_in_case.rb +10 -0
- data/lib/rubocop/cop/chef/correctness/invalid_platform_values_in_case.rb +10 -0
- data/lib/rubocop/cop/chef/correctness/invalid_value_for_platform_helper.rb +1 -0
- data/lib/rubocop/cop/chef/correctness/openssl_password_helpers.rb +1 -1
- data/lib/rubocop/cop/chef/correctness/platform_version_string_comparison.rb +66 -0
- data/lib/rubocop/cop/chef/correctness/powershell_delete_file.rb +5 -5
- data/lib/rubocop/cop/chef/correctness/powershell_file_exists.rb +1 -1
- data/lib/rubocop/cop/chef/correctness/resource_with_none_action.rb +3 -3
- data/lib/rubocop/cop/chef/correctness/ruby_guard_without_block.rb +91 -0
- data/lib/rubocop/cop/chef/correctness/service_resource.rb +71 -20
- data/lib/rubocop/cop/chef/deprecation/chef_handler_recipe.rb +8 -1
- data/lib/rubocop/cop/chef/deprecation/chef_rest.rb +4 -1
- data/lib/rubocop/cop/chef/deprecation/chef_shellout.rb +2 -2
- data/lib/rubocop/cop/chef/deprecation/chef_sugar_helpers.rb +6 -0
- data/lib/rubocop/cop/chef/deprecation/chef_windows_platform_helper.rb +1 -1
- data/lib/rubocop/cop/chef/deprecation/chocolatey_package_uninstall_action.rb +3 -3
- data/lib/rubocop/cop/chef/deprecation/depends_partial_search.rb +4 -0
- data/lib/rubocop/cop/chef/deprecation/deprecated_mixins.rb +2 -2
- data/lib/rubocop/cop/chef/deprecation/hwrp_without_provides.rb +4 -4
- data/lib/rubocop/cop/chef/deprecation/hwrp_without_unified_mode_true.rb +2 -2
- data/lib/rubocop/cop/chef/deprecation/inherits_compat_resource.rb +3 -3
- data/lib/rubocop/cop/chef/deprecation/legacy_yum_cookbook_recipes.rb +9 -1
- data/lib/rubocop/cop/chef/deprecation/locale_lc_all_property.rb +5 -0
- data/lib/rubocop/cop/chef/deprecation/resource_uses_only_resource_name.rb +9 -1
- data/lib/rubocop/cop/chef/deprecation/resource_uses_provider_base_method.rb +4 -0
- data/lib/rubocop/cop/chef/deprecation/ruby_block_create_action.rb +42 -3
- data/lib/rubocop/cop/chef/deprecation/use_automatic_resource_name.rb +9 -0
- data/lib/rubocop/cop/chef/deprecation/use_yaml_dump.rb +5 -0
- data/lib/rubocop/cop/chef/deprecation/xml_ruby_recipe.rb +5 -1
- data/lib/rubocop/cop/chef/modernize/apt_default_recipe.rb +1 -1
- data/lib/rubocop/cop/chef/modernize/build_essential.rb +4 -1
- data/lib/rubocop/cop/chef/modernize/chef_14_resources.rb +8 -0
- data/lib/rubocop/cop/chef/modernize/chef_15_resources.rb +11 -0
- data/lib/rubocop/cop/chef/modernize/chef_gem_nokogiri.rb +4 -0
- data/lib/rubocop/cop/chef/modernize/conditional_using_test.rb +10 -3
- data/lib/rubocop/cop/chef/modernize/cron_d_file_or_template.rb +6 -4
- data/lib/rubocop/cop/chef/modernize/databag_helpers.rb +6 -3
- data/lib/rubocop/cop/chef/modernize/depends_chef_vault_cookbook.rb +4 -0
- data/lib/rubocop/cop/chef/modernize/depends_chocolatey_cookbooks.rb +7 -0
- data/lib/rubocop/cop/chef/modernize/depends_kernel_module_cookbook.rb +6 -0
- data/lib/rubocop/cop/chef/modernize/depends_locale_cookbook.rb +6 -0
- data/lib/rubocop/cop/chef/modernize/depends_openssl_cookbook.rb +9 -0
- data/lib/rubocop/cop/chef/modernize/depends_timezone_lwrp_cookbook.rb +4 -0
- data/lib/rubocop/cop/chef/modernize/depends_windows_firewall_cookbook.rb +8 -0
- data/lib/rubocop/cop/chef/modernize/depends_zypper_cookbook.rb +7 -0
- data/lib/rubocop/cop/chef/modernize/dsl_include_in_resource.rb +1 -1
- data/lib/rubocop/cop/chef/modernize/execute_apt_update.rb +3 -1
- data/lib/rubocop/cop/chef/modernize/execute_archive_extract.rb +121 -0
- data/lib/rubocop/cop/chef/modernize/execute_update_alternatives.rb +100 -0
- data/lib/rubocop/cop/chef/modernize/includes_mixin_shellout.rb +4 -0
- data/lib/rubocop/cop/chef/modernize/libarchive_file.rb +5 -3
- data/lib/rubocop/cop/chef/modernize/ohai_default_recipe.rb +6 -1
- data/lib/rubocop/cop/chef/modernize/powershell_download_file.rb +64 -0
- data/lib/rubocop/cop/chef/modernize/powershell_expand_archive.rb +8 -1
- data/lib/rubocop/cop/chef/modernize/powershell_guard_interpreter.rb +4 -4
- data/lib/rubocop/cop/chef/modernize/sc_windows_resource.rb +2 -2
- data/lib/rubocop/cop/chef/modernize/seven_zip_archive.rb +7 -1
- data/lib/rubocop/cop/chef/modernize/shellouts_to_chocolatey.rb +15 -4
- data/lib/rubocop/cop/chef/modernize/use_require_relative.rb +1 -1
- data/lib/rubocop/cop/chef/modernize/windows_default_recipe.rb +1 -1
- data/lib/rubocop/cop/chef/modernize/windows_zipfile.rb +8 -2
- data/lib/rubocop/cop/chef/modernize/zipfile_resource.rb +7 -1
- data/lib/rubocop/cop/chef/modernize/zypper_repo.rb +2 -2
- data/lib/rubocop/cop/chef/redundant/custom_resource_with_allowed_actions.rb +10 -0
- data/lib/rubocop/cop/chef/redundant/double_compile_time.rb +22 -8
- data/lib/rubocop/cop/chef/redundant/service_guard_on_stop_disable.rb +117 -0
- data/lib/rubocop/cop/chef/redundant/string_property_with_nil_default.rb +2 -2
- data/lib/rubocop/cop/chef/redundant/unnecessary_name_property.rb +1 -1
- data/lib/rubocop/cop/chef/security/insecure_remote_file_source.rb +82 -0
- data/lib/rubocop/cop/chef/security/ssh_private_key.rb +9 -0
- data/lib/rubocop/cop/chef/sharing/empty_property_description.rb +62 -0
- data/lib/rubocop/cop/chef/style/include_recipe_with_parentheses.rb +5 -2
- data/lib/rubocop/cop/chef/style/true_false_resource_properties.rb +1 -1
- data/lib/rubocop/monkey_patches/directive_comment.rb +21 -3
- metadata +15 -4
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright:: Copyright (c) 2016-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
|
|
4
|
+
# Author:: Tim Smith (<tsmith84@gmail.com>)
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
module RuboCop
|
|
19
|
+
module Cop
|
|
20
|
+
module Chef
|
|
21
|
+
module Modernize
|
|
22
|
+
# Use the archive_file resource built into Chef Infra Client 15+ instead of shelling out to
|
|
23
|
+
# tar or unzip. The resource extracts tar, tar.gz, tar.bz2, tar.xz, and zip archives, and it
|
|
24
|
+
# only runs when the archive is newer than what was already extracted, where the shelled out
|
|
25
|
+
# command re-extracts on every converge.
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
#
|
|
29
|
+
# # bad
|
|
30
|
+
# execute 'extract nginx' do
|
|
31
|
+
# command "tar xzf #{Chef::Config[:file_cache_path]}/nginx.tar.gz -C /opt/nginx"
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# execute 'unzip -o /tmp/app.zip -d /opt/app'
|
|
35
|
+
#
|
|
36
|
+
# # good
|
|
37
|
+
# archive_file 'extract nginx' do
|
|
38
|
+
# path "#{Chef::Config[:file_cache_path]}/nginx.tar.gz"
|
|
39
|
+
# destination '/opt/nginx'
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
class ExecuteArchiveExtract < Base
|
|
43
|
+
include RuboCop::Chef::CookbookHelpers
|
|
44
|
+
extend TargetChefVersion
|
|
45
|
+
|
|
46
|
+
minimum_target_chef_version '15.0'
|
|
47
|
+
|
|
48
|
+
MSG = 'Use the archive_file resource built into Chef Infra Client 15+ instead of shelling out to tar or unzip'
|
|
49
|
+
RESTRICT_ON_SEND = [:execute].freeze
|
|
50
|
+
|
|
51
|
+
# `tar` extracts when its short flags include an x, or with the --extract long option.
|
|
52
|
+
# Anchoring the flag cluster directly after `tar` keeps `tar czf` (create), `tar tzf`
|
|
53
|
+
# (list), and `tar --exclude=.git -czf` from matching, since none of those put an x
|
|
54
|
+
# in the first cluster.
|
|
55
|
+
EXTRACT_COMMAND = %r{
|
|
56
|
+
\A\s*(?:\S*/)?(?:
|
|
57
|
+
tar\s+(?:-)?[a-z]*x[a-z]*(?:\s|\z) | # tar xzf / tar -xzf / tar zxvf
|
|
58
|
+
tar\s+--extract\b | # tar --extract --file
|
|
59
|
+
unzip(?:\s|\z) # unzip -o foo.zip -d /opt
|
|
60
|
+
)
|
|
61
|
+
}xi.freeze
|
|
62
|
+
|
|
63
|
+
# the shell resources whose script lives in a code property
|
|
64
|
+
SCRIPT_RESOURCES = %i(bash sh csh ksh zsh script).freeze
|
|
65
|
+
|
|
66
|
+
# A command that chains, pipes, or substitutes is doing more than extracting, so
|
|
67
|
+
# archive_file cannot replace it wholesale and the suggestion would be wrong.
|
|
68
|
+
SHELL_OPERATORS = ['&&', '||', ';', '|', '`', '$(', "\n"].freeze
|
|
69
|
+
|
|
70
|
+
def on_send(node)
|
|
71
|
+
command = node.arguments.first
|
|
72
|
+
return unless command
|
|
73
|
+
|
|
74
|
+
# Match on source rather than .value so an interpolated name such as
|
|
75
|
+
# execute "tar xzf #{node['foo']['tarball']}" is caught too -- that is a
|
|
76
|
+
# dstr node whose .value does not exist.
|
|
77
|
+
return unless %i(str dstr).include?(command.type)
|
|
78
|
+
|
|
79
|
+
add_offense(node, severity: :refactor) if extracts_archive?(unquote(command.source))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def on_block(node)
|
|
83
|
+
match_property_in_resource?(:execute, 'command', node) do |property|
|
|
84
|
+
report_property(node, property)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
match_property_in_resource?(SCRIPT_RESOURCES, 'code', node) do |property|
|
|
88
|
+
report_property(node, property)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
# strip the surrounding quotes off a string literal's source so the
|
|
95
|
+
# command regexes, which are anchored at the start, still match
|
|
96
|
+
#
|
|
97
|
+
# @param [String] source
|
|
98
|
+
#
|
|
99
|
+
# @return [String]
|
|
100
|
+
def unquote(source)
|
|
101
|
+
source.sub(/\A["']/, '').sub(/["']\z/, '')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def report_property(node, property)
|
|
105
|
+
command = method_arg_ast_to_string(property)
|
|
106
|
+
add_offense(node, severity: :refactor) if command && extracts_archive?(command)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @param [String] command
|
|
110
|
+
#
|
|
111
|
+
# @return [Boolean]
|
|
112
|
+
def extracts_archive?(command)
|
|
113
|
+
return false if SHELL_OPERATORS.any? { |operator| command.include?(operator) }
|
|
114
|
+
|
|
115
|
+
EXTRACT_COMMAND.match?(command)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright:: Copyright (c) 2016-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
|
|
4
|
+
# Author:: Tim Smith (<tsmith84@gmail.com>)
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
module RuboCop
|
|
19
|
+
module Cop
|
|
20
|
+
module Chef
|
|
21
|
+
module Modernize
|
|
22
|
+
# Chef Infra Client 16.0 and later includes an `alternatives` resource that should be used to
|
|
23
|
+
# manage alternatives links instead of shelling out to `update-alternatives` or `alternatives`.
|
|
24
|
+
# The resource is idempotent and handles both the Debian and RHEL flavours of the command, where
|
|
25
|
+
# an `execute` re-runs on every converge and reports the resource as updated every time.
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
#
|
|
29
|
+
# # bad
|
|
30
|
+
# execute 'install java alternative' do
|
|
31
|
+
# command 'update-alternatives --install /usr/bin/java java /usr/lib/jvm/jre-11/bin/java 1'
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# execute 'alternatives --set java /usr/lib/jvm/jre-11/bin/java'
|
|
35
|
+
#
|
|
36
|
+
# # good
|
|
37
|
+
# alternatives 'java' do
|
|
38
|
+
# link '/usr/bin/java'
|
|
39
|
+
# path '/usr/lib/jvm/jre-11/bin/java'
|
|
40
|
+
# priority 1
|
|
41
|
+
# action :install
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
class ExecuteUpdateAlternatives < Base
|
|
45
|
+
include RuboCop::Chef::CookbookHelpers
|
|
46
|
+
extend TargetChefVersion
|
|
47
|
+
|
|
48
|
+
minimum_target_chef_version '16.0'
|
|
49
|
+
|
|
50
|
+
MSG = 'Chef Infra Client 16.0 and later includes an alternatives resource that should be used to manage alternatives links instead of shelling out to update-alternatives or alternatives'
|
|
51
|
+
RESTRICT_ON_SEND = [:execute].freeze
|
|
52
|
+
|
|
53
|
+
# Debian ships update-alternatives and RHEL ships alternatives, and the resource drives both.
|
|
54
|
+
# Matching is limited to the four subcommands the resource can express: --install, --set,
|
|
55
|
+
# --auto, and --remove. The rest are deliberately left alone -- --config and --display are
|
|
56
|
+
# interactive or read only, and --remove-all has no resource equivalent.
|
|
57
|
+
ALTERNATIVES_COMMAND = %r{
|
|
58
|
+
\A\s*(?:/usr/sbin/|/usr/bin/|/sbin/|/bin/)? # an optional absolute path to the binary
|
|
59
|
+
(?:update-)?alternatives\s+
|
|
60
|
+
--(?:install|set|auto|remove(?!-all))\b
|
|
61
|
+
}x.freeze
|
|
62
|
+
|
|
63
|
+
# the shell resources whose script lives in a code property
|
|
64
|
+
SCRIPT_RESOURCES = %i(bash sh csh ksh zsh).freeze
|
|
65
|
+
|
|
66
|
+
def on_send(node)
|
|
67
|
+
command = node.arguments.first
|
|
68
|
+
return unless command&.str_type? && manages_alternatives?(command.value)
|
|
69
|
+
|
|
70
|
+
add_offense(node, severity: :refactor)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def on_block(node)
|
|
74
|
+
match_property_in_resource?(:execute, 'command', node) do |property|
|
|
75
|
+
report_property(node, property)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
match_property_in_resource?(SCRIPT_RESOURCES, 'code', node) do |property|
|
|
79
|
+
report_property(node, property)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def report_property(node, property)
|
|
86
|
+
command = method_arg_ast_to_string(property)
|
|
87
|
+
add_offense(node, severity: :refactor) if command && manages_alternatives?(command)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @param [String] command
|
|
91
|
+
#
|
|
92
|
+
# @return [Boolean]
|
|
93
|
+
def manages_alternatives?(command)
|
|
94
|
+
ALTERNATIVES_COMMAND.match?(command)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -29,6 +29,10 @@ module RuboCop
|
|
|
29
29
|
# require 'chef/mixin/powershell_out'
|
|
30
30
|
# include Chef::Mixin::PowershellOut
|
|
31
31
|
#
|
|
32
|
+
# # good
|
|
33
|
+
# # shell_out is available in resources and providers with no include
|
|
34
|
+
# shell_out!('/opt/app/bin/app --version')
|
|
35
|
+
#
|
|
32
36
|
class IncludingMixinShelloutInResources < Base
|
|
33
37
|
extend AutoCorrector
|
|
34
38
|
include RangeHelp
|
|
@@ -26,12 +26,12 @@ module RuboCop
|
|
|
26
26
|
# # bad
|
|
27
27
|
# depends 'libarchive'
|
|
28
28
|
#
|
|
29
|
-
# libarchive_file
|
|
29
|
+
# libarchive_file 'C:\file.zip' do
|
|
30
30
|
# path 'C:\expand_here'
|
|
31
31
|
# end
|
|
32
32
|
#
|
|
33
33
|
# # good
|
|
34
|
-
# archive_file
|
|
34
|
+
# archive_file 'C:\file.zip' do
|
|
35
35
|
# path 'C:\expand_here'
|
|
36
36
|
# end
|
|
37
37
|
#
|
|
@@ -44,8 +44,10 @@ module RuboCop
|
|
|
44
44
|
MSG = 'Use the archive_file resource built into Chef Infra Client 15+ instead of the libarchive_file resource from the libarchive cookbook'
|
|
45
45
|
RESTRICT_ON_SEND = [:libarchive_file, :notifies, :subscribes].freeze
|
|
46
46
|
|
|
47
|
+
# the notification timing is optional and defaults to :delayed, so the trailing
|
|
48
|
+
# argument is matched with ... rather than being required
|
|
47
49
|
def_node_matcher :notification_property?, <<-PATTERN
|
|
48
|
-
(send nil? {:notifies :subscribes} (sym _) $(...)
|
|
50
|
+
(send nil? {:notifies :subscribes} (sym _) $(...) ...)
|
|
49
51
|
PATTERN
|
|
50
52
|
|
|
51
53
|
def on_send(node)
|
|
@@ -27,12 +27,17 @@ module RuboCop
|
|
|
27
27
|
# include_recipe 'ohai::default'
|
|
28
28
|
# include_recipe 'ohai'
|
|
29
29
|
#
|
|
30
|
+
# # good
|
|
31
|
+
# ohai_plugin 'my_custom_plugin' do
|
|
32
|
+
# source_file 'my_plugin.rb'
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
30
35
|
class IncludingOhaiDefaultRecipe < Base
|
|
31
36
|
MSG = "Use the ohai_plugin resource to ship custom Ohai plugins instead of using the ohai::default recipe. If you're not shipping custom Ohai plugins, then you can remove this recipe entirely"
|
|
32
37
|
RESTRICT_ON_SEND = [:include_recipe].freeze
|
|
33
38
|
|
|
34
39
|
def_node_matcher :ohai_recipe_usage?, <<-PATTERN
|
|
35
|
-
(send nil? :include_recipe (str {"ohai" "ohai::default"}))
|
|
40
|
+
(send {nil? (send nil? :run_context)} :include_recipe (str {"ohai" "ohai::default"}))
|
|
36
41
|
PATTERN
|
|
37
42
|
|
|
38
43
|
def on_send(node)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright:: Copyright (c) 2016-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
|
|
4
|
+
# Author:: Tim Smith (<tsmith84@gmail.com>)
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
module RuboCop
|
|
19
|
+
module Cop
|
|
20
|
+
module Chef
|
|
21
|
+
module Modernize
|
|
22
|
+
# Use the `remote_file` resource to download files instead of shelling out to PowerShell.
|
|
23
|
+
# `remote_file` is idempotent, supports checksum verification, proxies, and conditional
|
|
24
|
+
# downloads with etags and last-modified headers, none of which a script gets for free.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
#
|
|
28
|
+
# # bad
|
|
29
|
+
# powershell_script 'download the installer' do
|
|
30
|
+
# code 'Invoke-WebRequest -Uri https://example.com/foo.msi -OutFile C:\foo.msi'
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# remote_file 'C:\foo.msi' do
|
|
35
|
+
# source 'https://example.com/foo.msi'
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
class PowershellDownloadFile < Base
|
|
39
|
+
include RuboCop::Chef::CookbookHelpers
|
|
40
|
+
|
|
41
|
+
MSG = 'Use the remote_file resource to download files instead of downloading them in a PowerShell script resource'
|
|
42
|
+
|
|
43
|
+
# the PowerShell ways of pulling a file down over HTTP
|
|
44
|
+
DOWNLOAD_COMMANDS = Regexp.union(
|
|
45
|
+
/invoke-webrequest\s/i,
|
|
46
|
+
/\bstart-bitstransfer\s/i,
|
|
47
|
+
/\bwget\s/i, # PowerShell alias for Invoke-WebRequest
|
|
48
|
+
/\bcurl\s/i, # PowerShell alias for Invoke-WebRequest
|
|
49
|
+
/system\.net\.webclient/i
|
|
50
|
+
).freeze
|
|
51
|
+
|
|
52
|
+
def on_block(node)
|
|
53
|
+
match_property_in_resource?(%i(powershell_script pwsh_script), 'code', node) do |code_property|
|
|
54
|
+
property_data = method_arg_ast_to_string(code_property)
|
|
55
|
+
next unless property_data&.match?(DOWNLOAD_COMMANDS)
|
|
56
|
+
|
|
57
|
+
add_offense(node, severity: :refactor)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -25,7 +25,14 @@ module RuboCop
|
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
27
|
# powershell_script 'Expand website' do
|
|
28
|
-
# code 'Expand-Archive "C
|
|
28
|
+
# code 'Expand-Archive "C:\file.zip" -DestinationPath "C:\inetpub\wwwroot" -Force'
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# # good
|
|
32
|
+
# archive_file 'Expand website' do
|
|
33
|
+
# path 'C:\file.zip'
|
|
34
|
+
# destination 'C:\inetpub\wwwroot'
|
|
35
|
+
# overwrite true
|
|
29
36
|
# end
|
|
30
37
|
#
|
|
31
38
|
class PowershellScriptExpandArchive < Base
|
|
@@ -25,22 +25,22 @@ module RuboCop
|
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
27
|
# powershell_script 'Create Directory' do
|
|
28
|
-
# code
|
|
28
|
+
# code 'New-Item -ItemType Directory -Force -Path C:\mydir'
|
|
29
29
|
# guard_interpreter :powershell_script
|
|
30
30
|
# end
|
|
31
31
|
#
|
|
32
32
|
# batch 'Create Directory' do
|
|
33
|
-
# code
|
|
33
|
+
# code 'mkdir C:\mydir'
|
|
34
34
|
# guard_interpreter :powershell_script
|
|
35
35
|
# end
|
|
36
36
|
#
|
|
37
37
|
# # good
|
|
38
38
|
# powershell_script 'Create Directory' do
|
|
39
|
-
# code
|
|
39
|
+
# code 'New-Item -ItemType Directory -Force -Path C:\mydir'
|
|
40
40
|
# end
|
|
41
41
|
#
|
|
42
42
|
# batch 'Create Directory' do
|
|
43
|
-
# code
|
|
43
|
+
# code 'mkdir C:\mydir'
|
|
44
44
|
# end
|
|
45
45
|
#
|
|
46
46
|
class PowerShellGuardInterpreter < Base
|
|
@@ -25,14 +25,14 @@ module RuboCop
|
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
27
|
# sc_windows 'chef-client' do
|
|
28
|
-
# path
|
|
28
|
+
# path 'C:\opscode\chef\bin'
|
|
29
29
|
# action :create
|
|
30
30
|
# end
|
|
31
31
|
#
|
|
32
32
|
# # good
|
|
33
33
|
# windows_service 'chef-client' do
|
|
34
34
|
# action :create
|
|
35
|
-
# binary_path_name
|
|
35
|
+
# binary_path_name 'C:\opscode\chef\bin'
|
|
36
36
|
# end
|
|
37
37
|
#
|
|
38
38
|
class WindowsScResource < Base
|
|
@@ -24,10 +24,16 @@ module RuboCop
|
|
|
24
24
|
# @example
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
|
-
# seven_zip_archive
|
|
27
|
+
# seven_zip_archive 'C:\file.zip' do
|
|
28
28
|
# path 'C:\expand_here'
|
|
29
29
|
# end
|
|
30
30
|
#
|
|
31
|
+
# # good
|
|
32
|
+
# archive_file 'expand file.zip' do
|
|
33
|
+
# path 'C:\file.zip'
|
|
34
|
+
# destination 'C:\expand_here'
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
31
37
|
class SevenZipArchiveResource < Base
|
|
32
38
|
extend TargetChefVersion
|
|
33
39
|
|
|
@@ -28,10 +28,21 @@ module RuboCop
|
|
|
28
28
|
# command "choco install --source=artifactory \"foo\" -y --no-progress --ignore-package-exit-codes"
|
|
29
29
|
# end
|
|
30
30
|
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
31
|
+
# powershell_script 'add artifactory choco source' do
|
|
32
|
+
# code "choco source add -n=artifactory -s='https://mycorp.jfrog.io/mycorp/api/nuget/chocolatey-remote' -u foo -p bar"
|
|
33
|
+
# not_if 'choco source list | findstr artifactory'
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# # good
|
|
37
|
+
# chocolatey_package 'foo' do
|
|
38
|
+
# source 'artifactory'
|
|
39
|
+
# options '--no-progress --ignore-package-exit-codes'
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# chocolatey_source 'artifactory' do
|
|
43
|
+
# source 'https://mycorp.jfrog.io/mycorp/api/nuget/chocolatey-remote'
|
|
44
|
+
# action :add
|
|
45
|
+
# end
|
|
35
46
|
#
|
|
36
47
|
class ShellOutToChocolatey < Base
|
|
37
48
|
include RuboCop::Chef::CookbookHelpers
|
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
|
35
35
|
RESTRICT_ON_SEND = [:include_recipe].freeze
|
|
36
36
|
|
|
37
37
|
def_node_matcher :windows_recipe_usage?, <<-PATTERN
|
|
38
|
-
(send nil? :include_recipe (str {"windows" "windows::default"}))
|
|
38
|
+
(send {nil? (send nil? :run_context)} :include_recipe (str {"windows" "windows::default"}))
|
|
39
39
|
PATTERN
|
|
40
40
|
|
|
41
41
|
def on_send(node)
|
|
@@ -24,8 +24,14 @@ module RuboCop
|
|
|
24
24
|
# @example
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
|
-
# windows_zipfile 'C
|
|
28
|
-
# source 'C
|
|
27
|
+
# windows_zipfile 'C:\files' do
|
|
28
|
+
# source 'C:\Temp\file.zip'
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# # good
|
|
32
|
+
# archive_file 'expand file.zip' do
|
|
33
|
+
# path 'C:\Temp\file.zip'
|
|
34
|
+
# destination 'C:\files'
|
|
29
35
|
# end
|
|
30
36
|
#
|
|
31
37
|
class WindowsZipfileUsage < Base
|
|
@@ -24,10 +24,16 @@ module RuboCop
|
|
|
24
24
|
# @example
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
|
-
# zipfile
|
|
27
|
+
# zipfile 'C:\file.zip' do
|
|
28
28
|
# path 'C:\expand_here'
|
|
29
29
|
# end
|
|
30
30
|
#
|
|
31
|
+
# # good
|
|
32
|
+
# archive_file 'expand file.zip' do
|
|
33
|
+
# path 'C:\file.zip'
|
|
34
|
+
# destination 'C:\expand_here'
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
31
37
|
class ZipfileResource < Base
|
|
32
38
|
include RuboCop::Chef::CookbookHelpers
|
|
33
39
|
extend TargetChefVersion
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
|
25
25
|
#
|
|
26
26
|
# # bad
|
|
27
27
|
# zypper_repo 'apache' do
|
|
28
|
-
# baseurl '
|
|
28
|
+
# baseurl 'https://download.opensuse.org/repositories/Apache'
|
|
29
29
|
# path '/openSUSE_Leap_42.2'
|
|
30
30
|
# type 'rpm-md'
|
|
31
31
|
# priority '100'
|
|
@@ -33,7 +33,7 @@ module RuboCop
|
|
|
33
33
|
#
|
|
34
34
|
# # good
|
|
35
35
|
# zypper_repository 'apache' do
|
|
36
|
-
# baseurl '
|
|
36
|
+
# baseurl 'https://download.opensuse.org/repositories/Apache'
|
|
37
37
|
# path '/openSUSE_Leap_42.2'
|
|
38
38
|
# type 'rpm-md'
|
|
39
39
|
# priority '100'
|
|
@@ -29,6 +29,16 @@ module RuboCop
|
|
|
29
29
|
# # also bad
|
|
30
30
|
# actions [:create, :remove]
|
|
31
31
|
#
|
|
32
|
+
# # good
|
|
33
|
+
# # Chef Infra Client derives the allowed actions from the actions you define
|
|
34
|
+
# action :create do
|
|
35
|
+
# # ...
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# action :remove do
|
|
39
|
+
# # ...
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
32
42
|
class CustomResourceWithAllowedActions < Base
|
|
33
43
|
include RangeHelp
|
|
34
44
|
extend AutoCorrector
|
|
@@ -41,23 +41,37 @@ module RuboCop
|
|
|
41
41
|
MSG = "If a resource includes the `compile_time` property there's no need to also use `.run_action(:some_action)` on the resource block."
|
|
42
42
|
RESTRICT_ON_SEND = [:run_action].freeze
|
|
43
43
|
|
|
44
|
-
def_node_matcher :
|
|
44
|
+
def_node_matcher :run_action_on_resource?, <<-PATTERN
|
|
45
45
|
(send
|
|
46
46
|
$(block
|
|
47
47
|
(send nil? ... )
|
|
48
48
|
(args)
|
|
49
|
-
|
|
50
|
-
(send nil? :action (sym $_) )
|
|
51
|
-
(send nil? :compile_time (true) )
|
|
52
|
-
...
|
|
53
|
-
>)
|
|
49
|
+
_
|
|
54
50
|
) :run_action (sym $_) )
|
|
55
51
|
PATTERN
|
|
56
52
|
|
|
53
|
+
def_node_search :compile_time_true?, '(send nil? :compile_time (true))'
|
|
54
|
+
def_node_search :action_nodes, '(send nil? :action $(sym _))'
|
|
55
|
+
|
|
57
56
|
def on_send(node)
|
|
58
|
-
|
|
57
|
+
run_action_on_resource?(node) do |resource, run_action|
|
|
58
|
+
next unless compile_time_true?(resource.body)
|
|
59
|
+
|
|
60
|
+
# without an explicit action there's nothing to rewrite: the resource runs its
|
|
61
|
+
# default action, and picking the replacement would mean knowing what that is.
|
|
62
|
+
# report it, but leave the fix to a human.
|
|
63
|
+
action = action_nodes(resource.body).first
|
|
64
|
+
unless action
|
|
65
|
+
add_offense(node.loc.selector, severity: :refactor)
|
|
66
|
+
next
|
|
67
|
+
end
|
|
68
|
+
|
|
59
69
|
add_offense(node.loc.selector, severity: :refactor) do |corrector|
|
|
60
|
-
|
|
70
|
+
# rewrite the action's value and drop the trailing .run_action(...). rewriting the
|
|
71
|
+
# whole block source instead would replace the action name wherever else it appears,
|
|
72
|
+
# renaming the resource itself in something like chef_gem 'nothing'
|
|
73
|
+
corrector.replace(action, ":#{run_action}")
|
|
74
|
+
corrector.remove(node.loc.dot.join(node.source_range.end))
|
|
61
75
|
end
|
|
62
76
|
end
|
|
63
77
|
end
|