module HostStatus
# rubocop:disable Style/GuardClause
class HostReportStatus < Status
def last_report
self.last_report = host.last_host_report_object_any_format unless @last_report_set
@last_report
end
def last_report=(report)
@last_report_set = true
@last_report = report
end
#
def change
last_report&.change || 0
end
def nochange
last_report&.nochange || 0
end
def failure
last_report&.failure || 0
end
def change?
change.positive?
end
def nochange?
nochange.positive?
end
def failure?
failure.positive?
end
#
#
def restarted
0
end
def failed_restarts
0
end
def skipped
0
end
#
def expected_report_interval
(reported_format_interval.presence || default_report_interval).to_i.minutes
end
def reported_format_interval
if host.params.key? "#{last_report.format.downcase}_interval"
host.params["#{last_report.format.downcase}_interval"]
else
Setting[:"#{last_report.format.downcase}_interval"]
end
end
def out_of_sync?
if (host && !host.enabled?) || no_reports? || out_of_sync_disabled?
false
else
!reported_at.nil? && reported_at < (Time.now.utc - expected_report_interval)
end
end
def no_reports?
host && last_report.nil?
end
def self.status_name
N_("Configuration")
end
# Constants are bit-mask friendly in case we want to query them in the DB
UNKNOWN = -0b000000000000010000000000000000 # -65536
FAILURES = -0b000000000000000000000000000001 # -1
EMPTY = 0b000000000000000000000000000000 # 0
NO_CHANGES = 0b000000000000000000000100000000 # 256
CHANGES = 0b000000000000010000000000000000 # 65536
LABELS = {
FAILURES => N_("Failure(s)"),
EMPTY => N_("Empty"),
NO_CHANGES => N_("No changes"),
CHANGES => N_("Changes applied"),
}.freeze
def to_label(_options = {})
if host && !host.enabled
return N_("Alerts disabled")
elsif out_of_sync?
return N_("Out of sync")
end
LABELS.fetch(to_status, N_("Unknown config status"))
end
def to_global(options = {})
handle_options(options)
if failure?
HostStatus::Global::ERROR
elsif out_of_sync?
HostStatus::Global::WARN
elsif no_reports? && (host.configuration? || Setting[:always_show_configuration_status])
HostStatus::Global::WARN
else
HostStatus::Global::OK
end
end
def to_status(options = {})
handle_options(options)
if host&.enabled && last_report.present?
if last_report.failure.positive?
FAILURES
elsif last_report.change.positive?
CHANGES
elsif last_report.nochange.positive?
NO_CHANGES
else
EMPTY
end
else
UNKNOWN
end
end
def relevant?(options = {})
handle_options(options)
host.configuration? || last_report.present? || Setting[:always_show_configuration_status]
end
def status_link
return @status_link if defined?(@status_link)
return @status_link = nil if last_report.nil?
return @status_link = nil unless User.current.can?(:view_host_reports, last_report, false)
@status_link = last_report && Rails.application.routes.url_helpers.host_report_path(last_report)
end
private
# Configuration status can be calculated from database state, but also reports can be
# passed in via options. In that case, report is matched with the host and set.
# Don't ask me why this is implemented this way, this is copy-paste from the original
# ConfigurationStatus in Foreman core.
def handle_options(options)
if options.key?(:last_reports) && !options[:last_reports].nil?
cached_report = options[:last_reports].find { |r| r.host_id == host_id }
self.last_report = cached_report
end
end
def update_timestamp
self.reported_at = last_report.try(:reported_at) || Time.now.utc
end
def default_report_interval
if host.params.key? 'outofsync_interval'
host.params['outofsync_interval']
else
Setting[:outofsync_interval]
end
end
def out_of_sync_disabled?
Setting[:"#{last_report.format.downcase}_out_of_sync_disabled"]
end
end
# rubocop:enable Style/GuardClause
end
HostStatus.status_registry.delete(HostStatus::ConfigurationStatus)
HostStatus.status_registry.add(HostStatus::HostReportStatus)