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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/config/chefstyle.yml +2 -0
  3. data/config/cookstyle.yml +145 -6
  4. data/lib/cookstyle/version.rb +2 -2
  5. data/lib/rubocop/chef/cookbook_helpers.rb +23 -0
  6. data/lib/rubocop/chef.rb +1 -1
  7. data/lib/rubocop/cop/chef/correctness/chef_application_fatal.rb +16 -4
  8. data/lib/rubocop/cop/chef/correctness/conditional_unified_mode_true.rb +91 -0
  9. data/lib/rubocop/cop/chef/correctness/empty_resource_guard.rb +18 -2
  10. data/lib/rubocop/cop/chef/correctness/execute_delete_file.rb +127 -0
  11. data/lib/rubocop/cop/chef/correctness/invalid_checksum.rb +79 -0
  12. data/lib/rubocop/cop/chef/correctness/invalid_platform_family_helper.rb +1 -1
  13. data/lib/rubocop/cop/chef/correctness/invalid_platform_family_values_in_case.rb +10 -0
  14. data/lib/rubocop/cop/chef/correctness/invalid_platform_values_in_case.rb +10 -0
  15. data/lib/rubocop/cop/chef/correctness/invalid_value_for_platform_helper.rb +1 -0
  16. data/lib/rubocop/cop/chef/correctness/openssl_password_helpers.rb +1 -1
  17. data/lib/rubocop/cop/chef/correctness/platform_version_string_comparison.rb +66 -0
  18. data/lib/rubocop/cop/chef/correctness/powershell_delete_file.rb +5 -5
  19. data/lib/rubocop/cop/chef/correctness/powershell_file_exists.rb +1 -1
  20. data/lib/rubocop/cop/chef/correctness/resource_with_none_action.rb +3 -3
  21. data/lib/rubocop/cop/chef/correctness/ruby_guard_without_block.rb +91 -0
  22. data/lib/rubocop/cop/chef/correctness/service_resource.rb +71 -20
  23. data/lib/rubocop/cop/chef/deprecation/chef_handler_recipe.rb +8 -1
  24. data/lib/rubocop/cop/chef/deprecation/chef_rest.rb +4 -1
  25. data/lib/rubocop/cop/chef/deprecation/chef_shellout.rb +2 -2
  26. data/lib/rubocop/cop/chef/deprecation/chef_sugar_helpers.rb +6 -0
  27. data/lib/rubocop/cop/chef/deprecation/chef_windows_platform_helper.rb +1 -1
  28. data/lib/rubocop/cop/chef/deprecation/chocolatey_package_uninstall_action.rb +3 -3
  29. data/lib/rubocop/cop/chef/deprecation/depends_partial_search.rb +4 -0
  30. data/lib/rubocop/cop/chef/deprecation/deprecated_mixins.rb +2 -2
  31. data/lib/rubocop/cop/chef/deprecation/hwrp_without_provides.rb +4 -4
  32. data/lib/rubocop/cop/chef/deprecation/hwrp_without_unified_mode_true.rb +2 -2
  33. data/lib/rubocop/cop/chef/deprecation/inherits_compat_resource.rb +3 -3
  34. data/lib/rubocop/cop/chef/deprecation/legacy_yum_cookbook_recipes.rb +9 -1
  35. data/lib/rubocop/cop/chef/deprecation/locale_lc_all_property.rb +5 -0
  36. data/lib/rubocop/cop/chef/deprecation/resource_uses_only_resource_name.rb +9 -1
  37. data/lib/rubocop/cop/chef/deprecation/resource_uses_provider_base_method.rb +4 -0
  38. data/lib/rubocop/cop/chef/deprecation/ruby_block_create_action.rb +42 -3
  39. data/lib/rubocop/cop/chef/deprecation/use_automatic_resource_name.rb +9 -0
  40. data/lib/rubocop/cop/chef/deprecation/use_yaml_dump.rb +5 -0
  41. data/lib/rubocop/cop/chef/deprecation/xml_ruby_recipe.rb +5 -1
  42. data/lib/rubocop/cop/chef/modernize/apt_default_recipe.rb +1 -1
  43. data/lib/rubocop/cop/chef/modernize/build_essential.rb +4 -1
  44. data/lib/rubocop/cop/chef/modernize/chef_14_resources.rb +8 -0
  45. data/lib/rubocop/cop/chef/modernize/chef_15_resources.rb +11 -0
  46. data/lib/rubocop/cop/chef/modernize/chef_gem_nokogiri.rb +4 -0
  47. data/lib/rubocop/cop/chef/modernize/conditional_using_test.rb +10 -3
  48. data/lib/rubocop/cop/chef/modernize/cron_d_file_or_template.rb +6 -4
  49. data/lib/rubocop/cop/chef/modernize/databag_helpers.rb +6 -3
  50. data/lib/rubocop/cop/chef/modernize/depends_chef_vault_cookbook.rb +4 -0
  51. data/lib/rubocop/cop/chef/modernize/depends_chocolatey_cookbooks.rb +7 -0
  52. data/lib/rubocop/cop/chef/modernize/depends_kernel_module_cookbook.rb +6 -0
  53. data/lib/rubocop/cop/chef/modernize/depends_locale_cookbook.rb +6 -0
  54. data/lib/rubocop/cop/chef/modernize/depends_openssl_cookbook.rb +9 -0
  55. data/lib/rubocop/cop/chef/modernize/depends_timezone_lwrp_cookbook.rb +4 -0
  56. data/lib/rubocop/cop/chef/modernize/depends_windows_firewall_cookbook.rb +8 -0
  57. data/lib/rubocop/cop/chef/modernize/depends_zypper_cookbook.rb +7 -0
  58. data/lib/rubocop/cop/chef/modernize/dsl_include_in_resource.rb +1 -1
  59. data/lib/rubocop/cop/chef/modernize/execute_apt_update.rb +3 -1
  60. data/lib/rubocop/cop/chef/modernize/execute_archive_extract.rb +121 -0
  61. data/lib/rubocop/cop/chef/modernize/execute_update_alternatives.rb +100 -0
  62. data/lib/rubocop/cop/chef/modernize/includes_mixin_shellout.rb +4 -0
  63. data/lib/rubocop/cop/chef/modernize/libarchive_file.rb +5 -3
  64. data/lib/rubocop/cop/chef/modernize/ohai_default_recipe.rb +6 -1
  65. data/lib/rubocop/cop/chef/modernize/powershell_download_file.rb +64 -0
  66. data/lib/rubocop/cop/chef/modernize/powershell_expand_archive.rb +8 -1
  67. data/lib/rubocop/cop/chef/modernize/powershell_guard_interpreter.rb +4 -4
  68. data/lib/rubocop/cop/chef/modernize/sc_windows_resource.rb +2 -2
  69. data/lib/rubocop/cop/chef/modernize/seven_zip_archive.rb +7 -1
  70. data/lib/rubocop/cop/chef/modernize/shellouts_to_chocolatey.rb +15 -4
  71. data/lib/rubocop/cop/chef/modernize/use_require_relative.rb +1 -1
  72. data/lib/rubocop/cop/chef/modernize/windows_default_recipe.rb +1 -1
  73. data/lib/rubocop/cop/chef/modernize/windows_zipfile.rb +8 -2
  74. data/lib/rubocop/cop/chef/modernize/zipfile_resource.rb +7 -1
  75. data/lib/rubocop/cop/chef/modernize/zypper_repo.rb +2 -2
  76. data/lib/rubocop/cop/chef/redundant/custom_resource_with_allowed_actions.rb +10 -0
  77. data/lib/rubocop/cop/chef/redundant/double_compile_time.rb +22 -8
  78. data/lib/rubocop/cop/chef/redundant/service_guard_on_stop_disable.rb +117 -0
  79. data/lib/rubocop/cop/chef/redundant/string_property_with_nil_default.rb +2 -2
  80. data/lib/rubocop/cop/chef/redundant/unnecessary_name_property.rb +1 -1
  81. data/lib/rubocop/cop/chef/security/insecure_remote_file_source.rb +82 -0
  82. data/lib/rubocop/cop/chef/security/ssh_private_key.rb +9 -0
  83. data/lib/rubocop/cop/chef/sharing/empty_property_description.rb +62 -0
  84. data/lib/rubocop/cop/chef/style/include_recipe_with_parentheses.rb +5 -2
  85. data/lib/rubocop/cop/chef/style/true_false_resource_properties.rb +1 -1
  86. data/lib/rubocop/monkey_patches/directive_comment.rb +21 -3
  87. 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 "C:\file.zip" do
29
+ # libarchive_file 'C:\file.zip' do
30
30
  # path 'C:\expand_here'
31
31
  # end
32
32
  #
33
33
  # # good
34
- # archive_file "C:\file.zip" do
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 _) $(...) (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:\\file.zip" -DestinationPath "C:\\inetpub\\wwwroot\\" -Force'
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 "New-Item -ItemType Directory -Force -Path C:\mydir"
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 "mkdir C:\mydir"
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 "New-Item -ItemType Directory -Force -Path C:\mydir"
39
+ # code 'New-Item -ItemType Directory -Force -Path C:\mydir'
40
40
  # end
41
41
  #
42
42
  # batch 'Create Directory' do
43
- # code "mkdir C:\mydir"
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 "C:\\opscode\\chef\\bin"
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 "C:\\opscode\\chef\\bin"
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 "C:\file.zip" do
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
- # 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
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
@@ -38,7 +38,7 @@ module RuboCop
38
38
  def_node_matcher :require_with_expand_path?, <<-PATTERN
39
39
  (send nil? :require
40
40
  (send
41
- (const nil? :File) :expand_path
41
+ (const {nil? cbase} :File) :expand_path
42
42
  $( str ... )
43
43
  $( str ... )))
44
44
  PATTERN
@@ -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:\\files\\' do
28
- # source 'C:\\Temp\\file.zip'
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 "C:\file.zip" do
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 'http://download.opensuse.org/repositories/Apache'
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 'http://download.opensuse.org/repositories/Apache'
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 :compile_time_and_run_action?, <<-PATTERN
44
+ def_node_matcher :run_action_on_resource?, <<-PATTERN
45
45
  (send
46
46
  $(block
47
47
  (send nil? ... )
48
48
  (args)
49
- (begin <
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
- compile_time_and_run_action?(node) do |resource, action, run_action|
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
- corrector.replace(node, resource.source.gsub(action.to_s, run_action.to_s))
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