require 'time'
require 'puppet/network/format_support'
require 'puppet/util/psych_support'
module Puppet
class Resource
# This class represents the result of evaluating a given resource. It
# contains file and line information about the source, events generated
# while evaluating the resource, timing information, and the status of the
# resource evaluation.
#
# @api private
class Status
include Puppet::Util::PsychSupport
include Puppet::Util::Tagging
include Puppet::Network::FormatSupport
# @!attribute [rw] file
# @return [String] The file where `@real_resource` was defined.
attr_accessor :file
# @!attribute [rw] line
# @return [Integer] The line number in the file where `@real_resource` was defined.
attr_accessor :line
# @!attribute [rw] evaluation_time
# @return [Float] The time elapsed in sections while evaluating `@real_resource`.
# measured in seconds.
attr_accessor :evaluation_time
# Boolean status types set while evaluating `@real_resource`.
STATES = [:skipped, :failed, :failed_to_restart, :restarted, :changed, :out_of_sync, :scheduled, :corrective_change]
attr_accessor(*STATES)
# @!attribute [r] source_description
# @return [String] The textual description of the path to `@real_resource`
# based on the containing structures. This is in contrast to
# `@containment_path` which is a list of containment path components.
# @example
# status.source_description #=> "/Stage[main]/Myclass/Exec[date]"
attr_reader :source_description
# @!attribute [r] containment_path
# @return [Array<String>] A list of resource references that contain
# `@real_resource`.
# @example A normal contained type
# status.containment_path #=> ["Stage[main]", "Myclass", "Exec[date]"]
# @example A whit associated with a class
# status.containment_path #=> ["Whit[Admissible_class[Main]]"]
attr_reader :containment_path
# @!attribute [r] time
# @return [Time] The time that this status object was created
attr_reader :time
# @!attribute [r] resource
# @return [String] The resource reference for `@real_resource`
attr_reader :resource
# @!attribute [r] change_count
# @return [Integer] A count of the successful changes made while
# evaluating `@real_resource`.
attr_reader :change_count
# @!attribute [r] out_of_sync_count
# @return [Integer] A count of the audited changes made while
# evaluating `@real_resource`.
attr_reader :out_of_sync_count
# @!attribute [r] resource_type
# @example
# status.resource_type #=> 'Notify'
# @return [String] The class name of `@real_resource`
attr_reader :resource_type
# @!attribute [rw] provider_used
# @return [String] The class name of the provider used for the resource
attr_accessor :provider_used
# @!attribute [r] title
# @return [String] The title of `@real_resource`
attr_reader :title
# @!attribute [r] events
# @return [Array<Puppet::Transaction::Event>] A list of events generated
# while evaluating `@real_resource`.
attr_reader :events
# @!attribute [r] corrective_change
# @return [Boolean] true if the resource contained a corrective change.
attr_reader :corrective_change
# @!attribute [rw] failed_dependencies
# @return [Array<Puppet::Resource>] A cache of all
# dependencies of this resource that failed to apply.
attr_accessor :failed_dependencies
def dependency_failed?
failed_dependencies && !failed_dependencies.empty?
end
def self.from_data_hash(data)
obj = self.allocate
obj.initialize_from_hash(data)
obj
end
# Provide a boolean method for each of the states.
STATES.each do |attr|
define_method("#{attr}?") do
!! send(attr)
end
end
def <<(event)
add_event(event)
self
end
def add_event(event)
@events << event
if event.status == 'failure'
self.failed = true
elsif event.status == 'success'
@change_count += 1
@changed = true
end
if event.status != 'audit'
@out_of_sync_count += 1
@out_of_sync = true
end
if event.corrective_change
@corrective_change = true
end
end
def failed_because(detail)
@real_resource.log_exception(detail, _("Could not evaluate: %{detail}") % { detail: detail })
# There's a contract (implicit unfortunately) that a status of failed
# will always be accompanied by an event with some explanatory power. This
# is useful for reporting/diagnostics/etc. So synthesize an event here
# with the exception detail as the message.
fail_with_event(detail.to_s)
end
# Both set the status state to failed and generate a corresponding
# Puppet::Transaction::Event failure with the given message.
# @param message [String] the reason for a status failure
def fail_with_event(message)
add_event(@real_resource.event(:name => :resource_error, :status => "failure", :message => message))
end
def initialize(resource)
@real_resource = resource
@source_description = resource.path
@containment_path = resource.pathbuilder
@resource = resource.to_s
@change_count = 0
@out_of_sync_count = 0
@changed = false
@out_of_sync = false
@skipped = false
@failed = false
@corrective_change = false
@file = resource.file
@line = resource.line
merge_tags_from(resource)
@time = Time.now
@events = []
@resource_type = resource.type.to_s.capitalize
@provider_used = resource.provider.class.name.to_s unless resource.provider.nil?
@title = resource.title
end
def initialize_from_hash(data)
@resource_type = data['resource_type']
@provider_used = data['provider_used']
@title = data['title']
@resource = data['resource']
@containment_path = data['containment_path']
@file = data['file']
@line = data['line']
@evaluation_time = data['evaluation_time']
@change_count = data['change_count']
@out_of_sync_count = data['out_of_sync_count']
@tags = Puppet::Util::TagSet.new(data['tags'])
@time = data['time']
@time = Time.parse(@time) if @time.is_a? String
@out_of_sync = data['out_of_sync']
@changed = data['changed']
@skipped = data['skipped']
@failed = data['failed']
@failed_to_restart = data['failed_to_restart']
@corrective_change = data['corrective_change']
@events = data['events'].map do |event|
# Older versions contain tags that causes Psych to create instances directly
event.is_a?(Puppet::Transaction::Event) ? event : Puppet::Transaction::Event.from_data_hash(event)
end
end
def to_data_hash
{
'title' => @title,
'file' => @file,
'line' => @line,
'resource' => @resource,
'resource_type' => @resource_type,
'provider_used' => @provider_used,
'containment_path' => @containment_path,
'evaluation_time' => @evaluation_time,
'tags' => @tags.to_a,
'time' => @time.iso8601(9),
'failed' => @failed,
'failed_to_restart' => self.failed_to_restart?,
'changed' => @changed,
'out_of_sync' => @out_of_sync,
'skipped' => @skipped,
'change_count' => @change_count,
'out_of_sync_count' => @out_of_sync_count,
'events' => @events.map { |event| event.to_data_hash },
'corrective_change' => @corrective_change,
}
end
end
end
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez