class Puppet::Transaction

the class that actually walks our resource/property tree, collects the changes, and performs them

@api private

Public Instance Methods

any_failed?() click to toggle source

Are there any failed resources in this transaction?

# File lib/puppet/transaction.rb, line 161
def any_failed?
  report.resource_statuses.values.detect { |status| status.failed? }
end
changed?() click to toggle source

Find all of the changed resources.

# File lib/puppet/transaction.rb, line 166
def changed?
  report.resource_statuses.values.find_all { |status| status.changed }.collect { |status| catalog.resource(status.resource) }
end
evaluate(&block) click to toggle source

This method does all the actual work of running a transaction. It collects all of the changes, executes them, and responds to any necessary events.

# File lib/puppet/transaction.rb, line 80
def evaluate(&block)
  block ||= method(:eval_resource)
  generator = AdditionalResourceGenerator.new(@catalog, relationship_graph, @prioritizer)
  @catalog.vertices.each { |resource| generator.generate_additional_resources(resource) }

  perform_pre_run_checks

  Puppet.info "Applying configuration version '#{catalog.version}'" if catalog.version

  continue_while = lambda { !stop_processing? }

  post_evalable_providers = Set.new
  pre_process = lambda do |resource|
    prov_class = resource.provider.class
    post_evalable_providers << prov_class if prov_class.respond_to?(:post_resource_eval)

    prefetch_if_necessary(resource)

    # If we generated resources, we don't know what they are now
    # blocking, so we opt to recompute it, rather than try to track every
    # change that would affect the number.
    relationship_graph.clear_blockers if generator.eval_generate(resource)
  end

  providerless_types = []
  overly_deferred_resource_handler = lambda do |resource|
    # We don't automatically assign unsuitable providers, so if there
    # is one, it must have been selected by the user.
    return if missing_tags?(resource)
    if resource.provider
      resource.err "Provider #{resource.provider.class.name} is not functional on this host"
    else
      providerless_types << resource.type
    end

    resource_status(resource).failed = true
  end

  canceled_resource_handler = lambda do |resource|
    resource_status(resource).skipped = true
    resource.debug "Transaction canceled, skipping"
  end

  teardown = lambda do
    # Just once per type. No need to punish the user.
    providerless_types.uniq.each do |type|
      Puppet.err "Could not find a suitable provider for #{type}"
    end

    post_evalable_providers.each do |provider|
      begin
        provider.post_resource_eval
      rescue => detail
        Puppet.log_exception(detail, "post_resource_eval failed for provider #{provider}")
      end
    end
  end

  relationship_graph.traverse(:while => continue_while,
                              :pre_process => pre_process,
                              :overly_deferred_resource_handler => overly_deferred_resource_handler,
                              :canceled_resource_handler => canceled_resource_handler,
                              :teardown => teardown) do |resource|
    if resource.is_a?(Puppet::Type::Component)
      Puppet.warning "Somehow left a component in the relationship graph"
    else
      resource.info "Starting to evaluate the resource" if Puppet[:evaltrace] and @catalog.host_config?
      seconds = thinmark { block.call(resource) }
      resource.info "Evaluated in %0.2f seconds" % seconds if Puppet[:evaltrace] and @catalog.host_config?
    end
  end

  Puppet.debug "Finishing transaction #{object_id}"
end
perform_pre_run_checks() click to toggle source

Invoke the pre_run_check hook in every resource in the catalog. This should (only) be called by #evaluate before applying the catalog.

@see #evaluate @see Puppet::Type#pre_run_check @raise [Puppet::Error] If any pre-run checks failed. @return [void]

# File lib/puppet/transaction.rb, line 58
def perform_pre_run_checks
  prerun_errors = {}

  @catalog.vertices.each do |res|
    begin
      res.pre_run_check
    rescue Puppet::Error => detail
      prerun_errors[res] = detail
    end
  end

  unless prerun_errors.empty?
    prerun_errors.each do |res, detail|
      res.log_exception(detail)
    end
    raise Puppet::Error, "Some pre-run checks failed"
  end
end
prefetch_if_necessary(resource) click to toggle source
# File lib/puppet/transaction.rb, line 185
def prefetch_if_necessary(resource)
  provider_class = resource.provider.class
  return unless provider_class.respond_to?(:prefetch) and !prefetched_providers[resource.type][provider_class.name]

  resources = resources_by_provider(resource.type, provider_class.name)

  if provider_class == resource.class.defaultprovider
    providerless_resources = resources_by_provider(resource.type, nil)
    providerless_resources.values.each {|res| res.provider = provider_class.name}
    resources.merge! providerless_resources
  end

  prefetch(provider_class, resources)
end
relationship_graph() click to toggle source
# File lib/puppet/transaction.rb, line 170
def relationship_graph
  catalog.relationship_graph(@prioritizer)
end
resource_status(resource) click to toggle source
# File lib/puppet/transaction.rb, line 174
def resource_status(resource)
  report.resource_statuses[resource.to_s] || add_resource_status(Puppet::Resource::Status.new(resource))
end
stop_processing?() click to toggle source

Wraps application run state check to flag need to interrupt processing

# File lib/puppet/transaction.rb, line 156
def stop_processing?
  Puppet::Application.stop_requested? && catalog.host_config?
end
tags() click to toggle source

The tags we should be checking.

# File lib/puppet/transaction.rb, line 179
def tags
  self.tags = Puppet[:tags] unless defined?(@tags)

  super
end

Public Class Methods

new(catalog, report, prioritizer) click to toggle source
# File lib/puppet/transaction.rb, line 34
def initialize(catalog, report, prioritizer)
  @catalog = catalog

  @report = report || Puppet::Transaction::Report.new("apply", catalog.version, catalog.environment)

  @prioritizer = prioritizer

  @report.add_times(:config_retrieval, @catalog.retrieval_duration || 0)

  @event_manager = Puppet::Transaction::EventManager.new(self)

  @resource_harness = Puppet::Transaction::ResourceHarness.new(self)

  @prefetched_providers = Hash.new { |h,k| h[k] = {} }
end