class Chef::ActionCollection

Attributes

action_records[R]
consumers[R]
events[R]
pending_updates[R]
run_context[R]

Public Class Methods

new(events, run_context = nil, action_records = []) click to toggle source
# File lib/chef/action_collection.rb, line 90
def initialize(events, run_context = nil, action_records = [])
  @action_records  = action_records
  @pending_updates = []
  @consumers       = []
  @events          = events
  @run_context     = run_context
end

Public Instance Methods

converge_failed(exception) click to toggle source

End of an unsuccessful converge used to fire off detect_unprocessed_resources.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 146
def converge_failed(exception)
  return if consumers.empty?
  detect_unprocessed_resources
end
cookbook_compilation_start(run_context) click to toggle source

This hook gives us the run_context immediately after it is created so that we can wire up this object to it.

This also causes the action_collection_registration event to fire, all consumers that have not yet registered with the action_collection must register via this callback. This is the latest point before resources actually start to get evaluated.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 126
def cookbook_compilation_start(run_context)
  run_context.action_collection = self
  # fire the action_colleciton_registration hook after cookbook_compilation_start -- last chance for consumers to register
  run_context.events.enqueue(:action_collection_registration, self)
  @run_context = run_context
end
filtered_collection(max_nesting: nil, up_to_date: true, skipped: true, updated: true, failed: true, unprocessed: true) click to toggle source

Allows getting at the action_records collection filtered by nesting level and status.

TODO: filtering by resource type+name

@return [Chef::ActionCollection]

# File lib/chef/action_collection.rb, line 106
def filtered_collection(max_nesting: nil, up_to_date: true, skipped: true, updated: true, failed: true, unprocessed: true)
  subrecords = action_records.select do |rec|
    ( max_nesting.nil? || rec.nesting_level <= max_nesting ) &&
      ( rec.status == :up_to_date && up_to_date ||
        rec.status == :skipped && skipped ||
        rec.status == :updated && updated ||
        rec.status == :failed && failed ||
        rec.status == :unprocessed && unprocessed )
  end
  self.class.new(events, run_context, subrecords)
end
register(object) click to toggle source

Consumers must call register – either directly or through the action_collection_registration hook. If nobody has registered any interest, then no action tracking will be done.

@params object [Object] callers should call with `self`

# File lib/chef/action_collection.rb, line 138
def register(object)
  consumers << object
end
resource_action_start(new_resource, action, notification_type = nil, notifier = nil) click to toggle source

Hook to start processing a resource. May be called within processing of an outer resource so the pending_updates array forms a stack that sub-resources are popped onto and off of. This is always called.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 157
def resource_action_start(new_resource, action, notification_type = nil, notifier = nil)
  return if consumers.empty?
  pending_updates << ActionRecord.new(new_resource, action, pending_updates.length)
end
resource_completed(new_resource) click to toggle source

Hook called after an action is completed. This is always called, even if the action fails.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 214
def resource_completed(new_resource)
  return if consumers.empty?
  current_record.elapsed_time = new_resource.elapsed_time

  # Verify if the resource has sensitive data and create a new blank resource with only
  # the name so we can report it back without sensitive data
  # XXX?: what about sensitive data in the current_resource?
  # FIXME: this needs to be display-logic
  if current_record.new_resource.sensitive
    klass = current_record.new_resource.class
    resource_name = current_record.new_resource.name
    current_record.new_resource = klass.new(resource_name)
  end

  action_records << pending_updates.pop
end
resource_current_state_loaded(new_resource, action, current_resource) click to toggle source

Hook called after a resource is loaded. If load_current_resource fails, this hook will not be called and current_resource will be nil, and the resource_failed hook will be called.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 167
def resource_current_state_loaded(new_resource, action, current_resource)
  return if consumers.empty?
  current_record.current_resource = current_resource
end
resource_failed(new_resource, action, exception) click to toggle source

Hook called after an action fails.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 204
def resource_failed(new_resource, action, exception)
  return if consumers.empty?
  current_record.status = :failed
  current_record.exception = exception
end
resource_skipped(resource, action, conditional) click to toggle source

Hook called after an action is determined to be skipped due to a conditional.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 185
def resource_skipped(resource, action, conditional)
  return if consumers.empty?
  current_record.status = :skipped
  current_record.conditional = conditional
end
resource_up_to_date(new_resource, action) click to toggle source

Hook called after an action is determined to be up to date.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 176
def resource_up_to_date(new_resource, action)
  return if consumers.empty?
  current_record.status = :up_to_date
end
resource_updated(new_resource, action) click to toggle source

Hook called after an action modifies the system and is marked updated.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 195
def resource_updated(new_resource, action)
  return if consumers.empty?
  current_record.status = :updated
end

Private Instance Methods

current_record() click to toggle source

@return [Chef::ActionCollection::ActionRecord] the current record we are working on at the top of the stack

# File lib/chef/action_collection.rb, line 234
def current_record
  pending_updates[-1]
end
detect_unprocessed_resources() click to toggle source

If the chef-client run fails in the middle, we are left with a half-completed resource_collection, this method is responsible for adding all of the resources which have not yet been touched. They are marked as being “unprocessed”.

# File lib/chef/action_collection.rb, line 242
def detect_unprocessed_resources
  run_context.resource_collection.all_resources.select { |resource| resource.executed_by_runner == false }.each do |resource|
    Array(resource.action).each do |action|
      record = ActionRecord.new(resource, action, 0)
      record.status = :unprocessed
      action_records << record
    end
  end
end