class Chef::ActionCollection

Attributes

action_records[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 92
def initialize(events, run_context = nil, action_records = [])
  @action_records  = action_records
  @pending_updates = []
  @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 147
def converge_failed(exception)
  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.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 127
def cookbook_compilation_start(run_context)
  run_context.action_collection = self
  # this hook is now poorly named since it is just a callback that lets other consumers snag a reference to the action_collection
  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 107
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 139
def register(object)
  Chef::Log.warn "the action collection no longer requires registration at #{caller[0]}"
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)
  pending_updates << ActionRecord.new(new_resource, action, pending_updates.length)
end
resource_after_state_loaded(new_resource, action, after_resource) click to toggle source

Hook called after an after resource is loaded. If load_after_resource fails, this hook will not be called and after_resource will be nil, and the resource_failed hook will be called.

(see EventDispatch::Base#)

# File lib/chef/action_collection.rb, line 175
def resource_after_state_loaded(new_resource, action, after_resource)
  current_record.after_resource = after_resource
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 218
def resource_completed(new_resource)
  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 current 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 166
def resource_current_state_loaded(new_resource, action, current_resource)
  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 208
def resource_failed(new_resource, action, exception)
  current_record.status = :failed
  current_record.exception = exception
  current_record.error_description = Formatters::ErrorMapper.resource_failed(new_resource, action, exception).for_json
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 191
def resource_skipped(resource, action, conditional)
  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 183
def resource_up_to_date(new_resource, action)
  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 200
def resource_updated(new_resource, action)
  current_record.status = :updated
end
resources() click to toggle source
# File lib/chef/action_collection.rb, line 119
def resources
  action_records.map(&:new_resource)
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 237
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 245
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