chef 17.1.35-universal-mingw32 → 17.2.29-universal-mingw32

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/lib/chef/action_collection.rb +6 -26
  4. data/lib/chef/application.rb +1 -1
  5. data/lib/chef/application/base.rb +15 -0
  6. data/lib/chef/client.rb +6 -0
  7. data/lib/chef/cookbook_version.rb +26 -4
  8. data/lib/chef/data_bag.rb +2 -1
  9. data/lib/chef/data_bag_item.rb +2 -1
  10. data/lib/chef/data_collector.rb +0 -1
  11. data/lib/chef/data_collector/run_end_message.rb +1 -1
  12. data/lib/chef/deprecated.rb +4 -0
  13. data/lib/chef/event_dispatch/base.rb +2 -1
  14. data/lib/chef/exceptions.rb +3 -0
  15. data/lib/chef/handler.rb +46 -8
  16. data/lib/chef/handler/slow_report.rb +66 -0
  17. data/lib/chef/node.rb +20 -19
  18. data/lib/chef/provider/support/zypper_repo.erb +4 -2
  19. data/lib/chef/provider/zypper_repository.rb +27 -31
  20. data/lib/chef/resource/alternatives.rb +5 -5
  21. data/lib/chef/resource/apt_preference.rb +2 -2
  22. data/lib/chef/resource/apt_repository.rb +2 -2
  23. data/lib/chef/resource/apt_update.rb +4 -4
  24. data/lib/chef/resource/build_essential.rb +1 -1
  25. data/lib/chef/resource/chef_client_config.rb +3 -3
  26. data/lib/chef/resource/chef_client_cron.rb +2 -2
  27. data/lib/chef/resource/chef_client_launchd.rb +2 -2
  28. data/lib/chef/resource/chef_client_scheduled_task.rb +14 -14
  29. data/lib/chef/resource/chef_client_systemd_timer.rb +2 -2
  30. data/lib/chef/resource/chef_handler.rb +2 -2
  31. data/lib/chef/resource/chef_sleep.rb +1 -1
  32. data/lib/chef/resource/chocolatey_feature.rb +2 -2
  33. data/lib/chef/resource/chocolatey_source.rb +1 -1
  34. data/lib/chef/resource/cron/cron_d.rb +4 -6
  35. data/lib/chef/resource/cron_access.rb +1 -1
  36. data/lib/chef/resource/dmg_package.rb +1 -1
  37. data/lib/chef/resource/group.rb +4 -4
  38. data/lib/chef/resource/homebrew_cask.rb +17 -6
  39. data/lib/chef/resource/homebrew_package.rb +1 -1
  40. data/lib/chef/resource/homebrew_tap.rb +4 -3
  41. data/lib/chef/resource/homebrew_update.rb +2 -2
  42. data/lib/chef/resource/hostname.rb +49 -7
  43. data/lib/chef/resource/inspec_waiver_file_entry.rb +6 -5
  44. data/lib/chef/resource/kernel_module.rb +6 -6
  45. data/lib/chef/resource/locale.rb +1 -1
  46. data/lib/chef/resource/macos_userdefaults.rb +2 -2
  47. data/lib/chef/resource/ohai_hint.rb +2 -6
  48. data/lib/chef/resource/openbsd_package.rb +17 -0
  49. data/lib/chef/resource/openssl_dhparam.rb +1 -2
  50. data/lib/chef/resource/openssl_ec_private_key.rb +1 -3
  51. data/lib/chef/resource/openssl_ec_public_key.rb +1 -3
  52. data/lib/chef/resource/openssl_rsa_private_key.rb +1 -3
  53. data/lib/chef/resource/openssl_rsa_public_key.rb +1 -3
  54. data/lib/chef/resource/openssl_x509_certificate.rb +1 -4
  55. data/lib/chef/resource/openssl_x509_crl.rb +1 -3
  56. data/lib/chef/resource/openssl_x509_request.rb +1 -3
  57. data/lib/chef/resource/osx_profile.rb +3 -3
  58. data/lib/chef/resource/plist.rb +1 -1
  59. data/lib/chef/resource/powershell_package_source.rb +2 -4
  60. data/lib/chef/resource/reboot.rb +38 -9
  61. data/lib/chef/resource/remote_directory.rb +2 -2
  62. data/lib/chef/resource/rhsm_errata.rb +0 -2
  63. data/lib/chef/resource/rhsm_errata_level.rb +1 -5
  64. data/lib/chef/resource/rhsm_repo.rb +15 -0
  65. data/lib/chef/resource/ssh_known_hosts_entry.rb +4 -7
  66. data/lib/chef/resource/sudo.rb +2 -6
  67. data/lib/chef/resource/swap_file.rb +2 -6
  68. data/lib/chef/resource/sysctl.rb +2 -2
  69. data/lib/chef/resource/timezone.rb +1 -1
  70. data/lib/chef/resource/user_ulimit.rb +2 -2
  71. data/lib/chef/resource/windows_ad_join.rb +2 -2
  72. data/lib/chef/resource/windows_audit_policy.rb +2 -2
  73. data/lib/chef/resource/windows_auto_run.rb +2 -2
  74. data/lib/chef/resource/windows_certificate.rb +1 -1
  75. data/lib/chef/resource/windows_dfs_folder.rb +2 -2
  76. data/lib/chef/resource/windows_dfs_namespace.rb +2 -2
  77. data/lib/chef/resource/windows_dns_record.rb +2 -2
  78. data/lib/chef/resource/windows_dns_zone.rb +2 -2
  79. data/lib/chef/resource/windows_feature.rb +3 -3
  80. data/lib/chef/resource/windows_feature_dism.rb +3 -5
  81. data/lib/chef/resource/windows_feature_powershell.rb +3 -3
  82. data/lib/chef/resource/windows_firewall_profile.rb +2 -2
  83. data/lib/chef/resource/windows_firewall_rule.rb +20 -6
  84. data/lib/chef/resource/windows_font.rb +1 -1
  85. data/lib/chef/resource/windows_pagefile.rb +103 -64
  86. data/lib/chef/resource/windows_path.rb +2 -2
  87. data/lib/chef/resource/windows_printer.rb +5 -20
  88. data/lib/chef/resource/windows_printer_port.rb +48 -65
  89. data/lib/chef/resource/windows_security_policy.rb +2 -2
  90. data/lib/chef/resource/windows_share.rb +2 -2
  91. data/lib/chef/resource/windows_shortcut.rb +1 -1
  92. data/lib/chef/resource/windows_task.rb +1 -1
  93. data/lib/chef/resource/windows_uac.rb +3 -5
  94. data/lib/chef/resource/windows_user_privilege.rb +2 -2
  95. data/lib/chef/resource/windows_workgroup.rb +2 -2
  96. data/lib/chef/resource/yum_package.rb +10 -10
  97. data/lib/chef/resource/zypper_package.rb +4 -4
  98. data/lib/chef/resource/zypper_repository.rb +28 -8
  99. data/lib/chef/resource_reporter.rb +0 -1
  100. data/lib/chef/version.rb +1 -1
  101. data/spec/functional/resource/windows_hostname_spec.rb +91 -0
  102. data/spec/functional/resource/windows_pagefile_spec.rb +98 -0
  103. data/spec/unit/cookbook_version_spec.rb +52 -0
  104. data/spec/unit/data_bag_item_spec.rb +2 -2
  105. data/spec/unit/data_bag_spec.rb +1 -1
  106. data/spec/unit/data_collector_spec.rb +47 -1
  107. data/spec/unit/handler_spec.rb +8 -2
  108. data/spec/unit/provider/zypper_repository_spec.rb +3 -10
  109. data/spec/unit/resource/windows_firewall_rule_spec.rb +12 -7
  110. data/spec/unit/resource/windows_pagefile_spec.rb +4 -9
  111. data/spec/unit/resource/zypper_repository_spec.rb +1 -1
  112. metadata +9 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d814772e55ced10ad9a25572951a3b2a947d99f34d04a8461832f98e9de30c82
4
- data.tar.gz: eaffd1bafbb17d03f396b57c2749ba9ab4cdce63167398bdeb73d3d655bb27b5
3
+ metadata.gz: 16349cc7cd44c42fa9e302a78df1ae63238d8826fad9f03e3ab7d64ed17398dc
4
+ data.tar.gz: 5bda57a2da605d02ce0cb2d7c8f808c7f76943e54f5565694eba0d223c5e1ecd
5
5
  SHA512:
6
- metadata.gz: b0d2752d08a72f130ef06263783ccb6c62b14edb653a19f9425c7cf7410a26668ebe6c8a8dbb845cc2705b5abe035ea9475b5c4e78eb43a5a5b43b1a4846c017
7
- data.tar.gz: 6d77cbb27f1ef920d28af4aeae4a5f39ee5841e523a16b65173c4cf8bff9d740b8e9e54ec66d02b17d73ec968595ffb27909033664415ca23461ac1e8e649125
6
+ metadata.gz: 67a2d97e1dc18947e71a55deac5c8c35f5c51d2fdb78beda851dcf8f1f0219afce48f2e6f8fe49d3bed7abb32409ea1de60377b343bc6fab9e427d201abce143
7
+ data.tar.gz: d8542bc72a0dd26d3b765968b77a45aeb5929618850c1a24af551bf74400c8f12dd7b1207c6638bd909254ace385d722e8a932a0b7a0ee9a8224b8e170407f42
data/Gemfile CHANGED
@@ -22,6 +22,7 @@ group(:omnibus_package) do
22
22
  gem "rb-readline"
23
23
  gem "inspec-core-bin", "~> 4.24" # need to provide the binaries for inspec
24
24
  gem "chef-vault"
25
+ gem "ed25519", "~> 1.2" # to make it possible to install knife into chef. Remove this in Chef 18
25
26
  end
26
27
 
27
28
  group(:omnibus_package, :pry) do
@@ -87,13 +87,11 @@ class Chef
87
87
  attr_reader :action_records
88
88
  attr_reader :pending_updates
89
89
  attr_reader :run_context
90
- attr_reader :consumers
91
90
  attr_reader :events
92
91
 
93
92
  def initialize(events, run_context = nil, action_records = [])
94
93
  @action_records = action_records
95
94
  @pending_updates = []
96
- @consumers = []
97
95
  @events = events
98
96
  @run_context = run_context
99
97
  end
@@ -118,17 +116,17 @@ class Chef
118
116
  self.class.new(events, run_context, subrecords)
119
117
  end
120
118
 
119
+ def resources
120
+ action_records.map(&:new_resource)
121
+ end
122
+
121
123
  # This hook gives us the run_context immediately after it is created so that we can wire up this object to it.
122
124
  #
123
- # This also causes the action_collection_registration event to fire, all consumers that have not yet registered with the
124
- # action_collection must register via this callback. This is the latest point before resources actually start to get
125
- # evaluated.
126
- #
127
125
  # (see EventDispatch::Base#)
128
126
  #
129
127
  def cookbook_compilation_start(run_context)
130
128
  run_context.action_collection = self
131
- # fire the action_colleciton_registration hook after cookbook_compilation_start -- last chance for consumers to register
129
+ # this hook is now poorly named since it is just a callback that lets other consumers snag a reference to the action_collection
132
130
  run_context.events.enqueue(:action_collection_registration, self)
133
131
  @run_context = run_context
134
132
  end
@@ -139,7 +137,7 @@ class Chef
139
137
  # @params object [Object] callers should call with `self`
140
138
  #
141
139
  def register(object)
142
- consumers << object
140
+ Chef::Log.warn "the action collection no longer requires registration at #{caller[0]}"
143
141
  end
144
142
 
145
143
  # End of an unsuccessful converge used to fire off detect_unprocessed_resources.
@@ -147,8 +145,6 @@ class Chef
147
145
  # (see EventDispatch::Base#)
148
146
  #
149
147
  def converge_failed(exception)
150
- return if consumers.empty?
151
-
152
148
  detect_unprocessed_resources
153
149
  end
154
150
 
@@ -159,8 +155,6 @@ class Chef
159
155
  # (see EventDispatch::Base#)
160
156
  #
161
157
  def resource_action_start(new_resource, action, notification_type = nil, notifier = nil)
162
- return if consumers.empty?
163
-
164
158
  pending_updates << ActionRecord.new(new_resource, action, pending_updates.length)
165
159
  end
166
160
 
@@ -170,8 +164,6 @@ class Chef
170
164
  # (see EventDispatch::Base#)
171
165
  #
172
166
  def resource_current_state_loaded(new_resource, action, current_resource)
173
- return if consumers.empty?
174
-
175
167
  current_record.current_resource = current_resource
176
168
  end
177
169
 
@@ -181,8 +173,6 @@ class Chef
181
173
  # (see EventDispatch::Base#)
182
174
  #
183
175
  def resource_after_state_loaded(new_resource, action, after_resource)
184
- return if consumers.empty?
185
-
186
176
  current_record.after_resource = after_resource
187
177
  end
188
178
 
@@ -191,8 +181,6 @@ class Chef
191
181
  # (see EventDispatch::Base#)
192
182
  #
193
183
  def resource_up_to_date(new_resource, action)
194
- return if consumers.empty?
195
-
196
184
  current_record.status = :up_to_date
197
185
  end
198
186
 
@@ -201,8 +189,6 @@ class Chef
201
189
  # (see EventDispatch::Base#)
202
190
  #
203
191
  def resource_skipped(resource, action, conditional)
204
- return if consumers.empty?
205
-
206
192
  current_record.status = :skipped
207
193
  current_record.conditional = conditional
208
194
  end
@@ -212,8 +198,6 @@ class Chef
212
198
  # (see EventDispatch::Base#)
213
199
  #
214
200
  def resource_updated(new_resource, action)
215
- return if consumers.empty?
216
-
217
201
  current_record.status = :updated
218
202
  end
219
203
 
@@ -222,8 +206,6 @@ class Chef
222
206
  # (see EventDispatch::Base#)
223
207
  #
224
208
  def resource_failed(new_resource, action, exception)
225
- return if consumers.empty?
226
-
227
209
  current_record.status = :failed
228
210
  current_record.exception = exception
229
211
  current_record.error_description = Formatters::ErrorMapper.resource_failed(new_resource, action, exception).for_json
@@ -234,8 +216,6 @@ class Chef
234
216
  # (see EventDispatch::Base#)
235
217
  #
236
218
  def resource_completed(new_resource)
237
- return if consumers.empty?
238
-
239
219
  current_record.elapsed_time = new_resource.elapsed_time
240
220
 
241
221
  # Verify if the resource has sensitive data and create a new blank resource with only
@@ -310,7 +310,7 @@ class Chef
310
310
  logger.info "Forking #{ChefUtils::Dist::Infra::PRODUCT} instance to converge..."
311
311
  pid = fork do
312
312
  # Want to allow forked processes to finish converging when
313
- # TERM singal is received (exit gracefully)
313
+ # TERM signal is received (exit gracefully)
314
314
  trap("TERM") do
315
315
  logger.debug("SIGTERM received during converge," +
316
316
  " finishing converge to exit normally (send SIGINT to terminate immediately)")
@@ -297,6 +297,21 @@ class Chef::Application::Base < Chef::Application
297
297
  long: "--named-run-list NAMED_RUN_LIST",
298
298
  description: "Use a policyfile's named run list instead of the default run list."
299
299
 
300
+ option :slow_report,
301
+ long: "--[no-]slow-report [COUNT]",
302
+ description: "List the slowest resources at the end of the run (default: 10).",
303
+ boolean: true,
304
+ default: false,
305
+ proc: lambda { |argument|
306
+ if argument.nil?
307
+ true
308
+ elsif argument == false
309
+ false
310
+ else
311
+ Integer(argument)
312
+ end
313
+ }
314
+
300
315
  IMMEDIATE_RUN_SIGNAL = "1".freeze
301
316
  RECONFIGURE_SIGNAL = "H".freeze
302
317
 
data/lib/chef/client.rb CHANGED
@@ -863,6 +863,12 @@ class Chef
863
863
  end
864
864
 
865
865
  def start_profiling
866
+ if Chef::Config[:slow_report]
867
+ require_relative "handler/slow_report"
868
+
869
+ Chef::Config.report_handlers << Chef::Handler::SlowReport.new(Chef::Config[:slow_report])
870
+ end
871
+
866
872
  return unless Chef::Config[:profile_ruby]
867
873
 
868
874
  profiling_prereqs!
@@ -138,11 +138,14 @@ class Chef
138
138
  end
139
139
 
140
140
  def recipe_yml_filenames_by_name
141
- @recipe_ym_filenames_by_name ||= begin
141
+ @recipe_yml_filenames_by_name ||= begin
142
142
  name_map = yml_filenames_by_name(files_for("recipes"))
143
- root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "root_files/recipe.yml" }
143
+ root_alias = cookbook_manifest.root_files.find { |record|
144
+ record[:name] == "root_files/recipe.yml" ||
145
+ record[:name] == "root_files/recipe.yaml"
146
+ }
144
147
  if root_alias
145
- Chef::Log.error("Cookbook #{name} contains both recipe.yml and and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
148
+ Chef::Log.error("Cookbook #{name} contains both recipe.yml and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
146
149
  name_map["default"] = root_alias[:full_path]
147
150
  end
148
151
  name_map
@@ -582,8 +585,27 @@ class Chef
582
585
  records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
583
586
  end
584
587
 
588
+ # Filters YAML files from the superset of provided files.
589
+ # Checks for duplicate basenames with differing extensions (eg yaml v yml)
590
+ # and raises error if any are detected.
591
+ # This prevents us from arbitrarily the ".yaml" or ".yml" version when both are present,
592
+ # because we don't know which is correct.
593
+ # This method runs in O(n^2) where N = number of yml files present. This number should be consistently
594
+ # low enough that there's no noticeable perf impact.
585
595
  def yml_filenames_by_name(records)
586
- records.select { |record| record[:name] =~ /\.yml$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".yml")] = record[:full_path]; memo }
596
+ yml_files = records.select { |record| record[:name] =~ /\.(y[a]?ml)$/ }
597
+ result = yml_files.inject({}) do |acc, record|
598
+ filename = record[:name]
599
+ base_dup_name = File.join(File.dirname(filename), File.basename(filename, File.extname(filename)))
600
+ yml_files.each do |other|
601
+ if other[:name] =~ /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/
602
+ raise Chef::Exceptions::AmbiguousYAMLFile.new("Cookbook #{name}@#{version} contains ambiguous files: #{filename} and #{other[:name]}. Please update the cookbook to remove the incorrect file.")
603
+ end
604
+ end
605
+ acc[File.basename(record[:name], File.extname(record[:name]))] = record[:full_path]
606
+ acc
607
+ end
608
+ result
587
609
  end
588
610
 
589
611
  def file_vendor
data/lib/chef/data_bag.rb CHANGED
@@ -32,7 +32,8 @@ class Chef
32
32
  include Chef::Mixin::FromFile
33
33
  include Chef::Mixin::ParamsValidate
34
34
 
35
- VALID_NAME = /^[\.\-[:alnum:]_]+$/.freeze
35
+ # Regex reference: https://rubular.com/r/oIMySIO4USPm5x
36
+ VALID_NAME = /^[\-[:alnum:]_]+$/.freeze
36
37
  RESERVED_NAMES = /^(node|role|environment|client)$/.freeze
37
38
 
38
39
  def self.validate_name!(name)
@@ -36,7 +36,8 @@ class Chef
36
36
  include Chef::Mixin::FromFile
37
37
  include Chef::Mixin::ParamsValidate
38
38
 
39
- VALID_ID = /^[\.\-[:alnum:]_]+$/.freeze
39
+ # Regex reference: https://rubular.com/r/oIMySIO4USPm5x
40
+ VALID_ID = /^[\-[:alnum:]_]+$/.freeze
40
41
 
41
42
  def self.validate_id!(id_str)
42
43
  if id_str.nil? || ( id_str !~ VALID_ID )
@@ -104,7 +104,6 @@ class Chef
104
104
  #
105
105
  def action_collection_registration(action_collection)
106
106
  @action_collection = action_collection
107
- action_collection.register(self)
108
107
  end
109
108
 
110
109
  # - Creates and writes our NodeUUID back to the node object
@@ -51,7 +51,7 @@ class Chef
51
51
  "id" => run_status&.run_id,
52
52
  "message_version" => "1.1.0",
53
53
  "message_type" => "run_converge",
54
- "node" => node || {},
54
+ "node" => node&.data_for_save || {},
55
55
  "node_name" => node&.name || data_collector.node_name,
56
56
  "organization_name" => organization,
57
57
  "resources" => all_action_records(action_collection),
@@ -253,6 +253,10 @@ class Chef
253
253
  target 33
254
254
  end
255
255
 
256
+ class AttributeWhitelistConfiguration < Base
257
+ target 34
258
+ end
259
+
256
260
  class Generic < Base
257
261
  def url
258
262
  "https://docs.chef.io/chef_deprecations_client/"
@@ -221,7 +221,8 @@ class Chef
221
221
  # Called before convergence starts
222
222
  def converge_start(run_context); end
223
223
 
224
- # Callback hook for handlers to register their interest in the action_collection
224
+ # Callback hook for handlers to grab a reference to the action_collection
225
+ # (sent before compiling cookbooks, consumers can also find it off the run_context.action_collection)
225
226
  def action_collection_registration(action_collection); end
226
227
 
227
228
  # Called when the converge phase is finished.
@@ -174,6 +174,9 @@ class Chef
174
174
  class CannotDetermineWindowsInstallerType < Package; end
175
175
  class NoWindowsPackageSource < Package; end
176
176
 
177
+ # for example, if both recipes/default.yml, recipes/default.yaml are present
178
+ class AmbiguousYAMLFile < RuntimeError; end
179
+
177
180
  # Can not create staging file during file deployment
178
181
  class FileContentStagingError < RuntimeError
179
182
  def initialize(errors)
data/lib/chef/handler.rb CHANGED
@@ -55,6 +55,12 @@ class Chef
55
55
  #
56
56
  class Handler
57
57
 
58
+ # FIXME: Chef::Handler should probably inherit from EventDispatch::Base
59
+ # and should wire up to those events rather than the "notifications" system
60
+ # which is hanging off of Chef::Client. Those "notifications" could then be
61
+ # deprecated in favor of events, and this class could become decoupled from
62
+ # the Chef::Client object.
63
+
58
64
  def self.handler_for(*args)
59
65
  if args.include?(:start)
60
66
  Chef::Config[:start_handlers] ||= []
@@ -207,17 +213,45 @@ class Chef
207
213
  # The Chef::Node for this client run
208
214
  def_delegator :@run_status, :node
209
215
 
210
- ##
211
- # :method: all_resources
216
+ # @return Array<Chef::Resource> all resources other than unprocessed
212
217
  #
213
- # An Array containing all resources in the chef run's resource_collection
214
- def_delegator :@run_status, :all_resources
218
+ def all_resources
219
+ @all_resources ||= action_collection&.filtered_collection(unprocessed: false)&.resources || []
220
+ end
215
221
 
216
- ##
217
- # :method: updated_resources
222
+ # @return Array<Chef::Resource> all updated resources
223
+ #
224
+ def updated_resources
225
+ @updated_resources ||= action_collection&.filtered_collection(up_to_date: false, skipped: false, failed: false, unprocessed: false)&.resources || []
226
+ end
227
+
228
+ # @return Array<Chef::Resource> all up_to_date resources
229
+ #
230
+ def up_to_date_resources
231
+ @up_to_date_resources ||= action_collection&.filtered_collection(updated: false, skipped: false, failed: false, unprocessed: false)&.resources || []
232
+ end
233
+
234
+ # @return Array<Chef::Resource> all failed resources
218
235
  #
219
- # An Array containing all resources that were updated during the chef run
220
- def_delegator :@run_status, :updated_resources
236
+ def failed_resources
237
+ @failed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, skipped: false, unprocessed: false)&.resources || []
238
+ end
239
+
240
+ # @return Array<Chef::Resource> all skipped resources
241
+ #
242
+ def skipped_resources
243
+ @skipped_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, unprocessed: false)&.resources || []
244
+ end
245
+
246
+ # Unprocessed resources are those which are left over in the outer recipe context when a run fails.
247
+ # Sub-resources of unprocessed resourced are impossible to capture because they would require processing
248
+ # the outer resource.
249
+ #
250
+ # @return Array<Chef::Resource> all unprocessed resources
251
+ #
252
+ def unprocessed_resources
253
+ @unprocessed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, skipped: false)&.resources || []
254
+ end
221
255
 
222
256
  ##
223
257
  # :method: success?
@@ -232,6 +266,10 @@ class Chef
232
266
  # Did the chef run fail? True if the chef run raised an uncaught exception
233
267
  def_delegator :@run_status, :failed?
234
268
 
269
+ def action_collection
270
+ @run_status.run_context.action_collection
271
+ end
272
+
235
273
  # The main entry point for report handling. Subclasses should override this
236
274
  # method with their own report handling logic.
237
275
  def report; end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
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
+ require_relative "../handler"
19
+ require "tty/table" unless defined?(TTY::Table)
20
+
21
+ class Chef
22
+ class Handler
23
+ class SlowReport < ::Chef::Handler
24
+ attr_accessor :amount
25
+
26
+ def initialize(amount)
27
+ @amount = Integer(amount) rescue nil
28
+ @amount ||= 10
29
+ end
30
+
31
+ def report
32
+ if count == 0
33
+ puts "\nNo resources to profile\n\n"
34
+ return
35
+ end
36
+
37
+ top = all_records.sort_by(&:elapsed_time).last(amount).reverse
38
+ data = top.map { |r| [ r.new_resource.to_s, r.elapsed_time, r.action, r.new_resource.cookbook_name, r.new_resource.recipe_name, stripped_source_line(r.new_resource) ] }
39
+ puts "\nTop #{count} slowest #{count == 1 ? "resource" : "resources"}:\n\n"
40
+ table = TTY::Table.new(%w{resource elapsed_time action cookbook recipe source}, data)
41
+ rendered = table.render do |renderer|
42
+ renderer.border do
43
+ mid "-"
44
+ mid_mid " "
45
+ end
46
+ end
47
+ puts rendered
48
+ puts "\n"
49
+ end
50
+
51
+ def all_records
52
+ @all_records ||= action_collection&.filtered_collection(unprocessed: false) || []
53
+ end
54
+
55
+ def count
56
+ num = all_resources.count
57
+ num > amount ? amount : num
58
+ end
59
+
60
+ def stripped_source_line(resource)
61
+ # strip the leading path off of the source line
62
+ resource.source_line.gsub(%r{.*/cookbooks/}, "").gsub(%r{.*/chef-[0-9\.]+/}, "")
63
+ end
64
+ end
65
+ end
66
+ end