# 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