app/models/host_status/execution_status.rb
class HostStatus::ExecutionStatus < HostStatus::Status
# execution finished successfully
OK = 0
# execution finished with error
ERROR = 1
# execution hasn't started yet, either scheduled to future or executor didn't create task yet
QUEUED = 2
# execution is in progress, dynflow task was created
RUNNING = 3
# execution has been cancelled
CANCELLED = 4
# mapping to string representation
STATUS_NAMES = { OK => 'succeeded', ERROR => 'failed', QUEUED => 'queued', RUNNING => 'running', CANCELLED => 'cancelled' }.freeze
def relevant?(*args)
host.get_status(HostStatus::ExecutionStatus).present?
end
def to_status(options = {})
if self.new_record?
ExecutionTaskStatusMapper.new(last_stopped_task).status
else
self.status
end
end
def to_global(options = {})
if to_status(options) == ERROR
return HostStatus::Global::ERROR
else
return HostStatus::Global::OK
end
end
def self.status_name
N_('Execution')
end
def to_label(options = {})
case to_status(options)
when OK
N_('Last execution succeeded')
when CANCELLED
N_('Last execution cancelled')
when ERROR
N_('Last execution failed')
else
N_('Unknown execution status')
end
end
def status_link
job_invocation = last_stopped_task&.parent_task&.job_invocations&.first
return unless job_invocation
return nil unless User.current.can?(:view_job_invocations, job_invocation)
Rails.application.routes.url_helpers.job_invocation_path(job_invocation)
end
class ExecutionTaskStatusMapper
attr_accessor :task
def self.sql_conditions_for(status)
status = STATUS_NAMES.key(status) if status.is_a?(String)
case status
when OK
[ "foreman_tasks_tasks.state = 'stopped' AND foreman_tasks_tasks.result = 'success'" ]
when CANCELLED
[ "foreman_tasks_tasks.state = 'stopped' AND foreman_tasks_tasks.result = 'cancelled'" ]
when ERROR
[ "foreman_tasks_tasks.state = 'stopped' AND (foreman_tasks_tasks.result = 'error' OR foreman_tasks_tasks.result = 'warning')" ]
when QUEUED
[ "foreman_tasks_tasks.state = 'scheduled' OR foreman_tasks_tasks.state IS NULL" ]
when RUNNING
[ "foreman_tasks_tasks.state <> 'stopped'" ]
else
[ '1 = 0' ]
end
end
def initialize(task)
self.task = task
end
def status
if task.nil? || task.state == 'scheduled'
QUEUED
elsif task.state == 'stopped' && task.result == 'success'
OK
elsif task.state == 'stopped' && task.result == 'cancelled'
CANCELLED
elsif task.pending?
RUNNING
else
ERROR
end
end
def status_label
STATUS_NAMES[status]
end
end
private
def last_stopped_task
@last_stopped_task ||= execution_tasks.order(:started_at).where(:state => 'stopped').last
end
def execution_tasks
ForemanTasks::Task::DynflowTask.for_action(Actions::RemoteExecution::RunHostJob).for_resource(host)
end
end