class Transaction::ResourceHarness

Attributes

transaction[R]

Public Class Methods

new(transaction) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 152
def initialize(transaction)
  @transaction = transaction
end

Public Instance Methods

allow_changes?(resource) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 9
def allow_changes?(resource)
  if resource.purging? and resource.deleting? and deps = relationship_graph.dependents(resource)              and ! deps.empty? and deps.detect { |d| ! d.deleting? }
    deplabel = deps.collect { |r| r.ref }.join(",")
    plurality = deps.length > 1 ? "":"s"
    resource.warning "#{deplabel} still depend#{plurality} on me -- not purging"
    false
  else
    true
  end
end
apply_parameter(property, current_value, do_audit, historical_value) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 101
def apply_parameter(property, current_value, do_audit, historical_value)
  event = create_change_event(property, current_value, do_audit, historical_value)

  if do_audit && historical_value && historical_value != current_value
    brief_audit_message = " (previously recorded value was #{property.is_to_s(historical_value)})"
  else
    brief_audit_message = ""
  end

  if property.noop
    event.message = "current_value #{property.is_to_s(current_value)}, should be #{property.should_to_s(property.should)} (noop)#{brief_audit_message}"
    event.status = "noop"
  else
    property.sync
    event.message = [ property.change_to_s(current_value, property.should), brief_audit_message ].join
    event.status = "success"
  end
  event
rescue => detail
  Puppet.log_exception(detail)
  event.status = "failure"

  event.message = "change from #{property.is_to_s(current_value)} to #{property.should_to_s(property.should)} failed: #{detail}"
  event
ensure
  event.send_log
end
cache(resource, name, value) click to toggle source

Used mostly for scheduling and auditing at this point.

# File lib/puppet/transaction/resource_harness.rb, line 27
def cache(resource, name, value)
  Puppet::Util::Storage.cache(resource)[name] = value
end
cached(resource, name) click to toggle source

Used mostly for scheduling and auditing at this point.

# File lib/puppet/transaction/resource_harness.rb, line 22
def cached(resource, name)
  Puppet::Util::Storage.cache(resource)[name]
end
create_change_event(property, current_value, do_audit, historical_value) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 84
def create_change_event(property, current_value, do_audit, historical_value)
  event = property.event
  event.previous_value = current_value
  event.desired_value = property.should
  event.historical_value = historical_value

  if do_audit
    event.audited = true
    event.status = "audit"
    if historical_value != current_value
      event.message = "audit change: previously recorded value #{property.is_to_s(historical_value)} has been changed to #{property.is_to_s(current_value)}"
    end
  end

  event
end
evaluate(resource) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 129
def evaluate(resource)
  start = Time.now
  status = Puppet::Resource::Status.new(resource)

  perform_changes(resource).each do |event|
    status << event
  end

  if status.changed? && ! resource.noop?
    cache(resource, :synced, Time.now)
    resource.flush if resource.respond_to?(:flush)
  end

  return status
rescue => detail
  resource.fail "Could not create resource status: #{detail}" unless status
  resource.log_exception(detail, "Could not evaluate: #{detail}")
  status.failed = true
  return status
ensure
  (status.evaluation_time = Time.now - start) if status
end
perform_changes(resource) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 31
def perform_changes(resource)
  current = resource.retrieve_resource

  cache resource, :checked, Time.now

  return [] if ! allow_changes?(resource)

  current_values = current.to_hash
  historical_values = Puppet::Util::Storage.cache(resource).dup
  desired_values = {}
  resource.properties.each do |property|
    desired_values[property.name] = property.should
  end
  audited_params = (resource[:audit] || []).map { |p| p.to_sym }
  synced_params = []

  # Record the current state in state.yml.
  audited_params.each do |param|
    cache(resource, param, current_values[param])
  end

  # Update the machine state & create logs/events
  events = []
  ensure_param = resource.parameter(:ensure)
  if desired_values[:ensure] && !ensure_param.safe_insync?(current_values[:ensure])
    events << apply_parameter(ensure_param, current_values[:ensure], audited_params.include?(:ensure), historical_values[:ensure])
    synced_params << :ensure
  elsif current_values[:ensure] != :absent
    work_order = resource.properties # Note: only the resource knows what order to apply changes in
    work_order.each do |param|
      if desired_values[param.name] && !param.safe_insync?(current_values[param.name])
        events << apply_parameter(param, current_values[param.name], audited_params.include?(param.name), historical_values[param.name])
        synced_params << param.name
      end
    end
  end

  # Add more events to capture audit results
  audited_params.each do |param_name|
    if historical_values.include?(param_name)
      if historical_values[param_name] != current_values[param_name] && !synced_params.include?(param_name)
        event = create_change_event(resource.parameter(param_name), current_values[param_name], true, historical_values[param_name])
        event.send_log
        events << event
      end
    else
      resource.property(param_name).notice "audit change: newly-recorded value #{current_values[param_name]}"
    end
  end

  events
end
schedule(resource) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 168
def schedule(resource)
  unless resource.catalog
    resource.warning "Cannot schedule without a schedule-containing catalog"
    return nil
  end

  return nil unless name = resource[:schedule]
  resource.catalog.resource(:schedule, name) || resource.fail("Could not find schedule #{name}")
end
scheduled?(status, resource) click to toggle source
# File lib/puppet/transaction/resource_harness.rb, line 156
def scheduled?(status, resource)
  return true if Puppet[:ignoreschedules]
  return true unless schedule = schedule(resource)

  # We use 'checked' here instead of 'synced' because otherwise we'll
  # end up checking most resources most times, because they will generally
  # have been synced a long time ago (e.g., a file only gets updated
  # once a month on the server and its schedule is daily; the last sync time
  # will have been a month ago, so we'd end up checking every run).
  schedule.match?(cached(resource, :checked).to_i)
end