Class: Actions::ForemanOpenbolt::PollTaskStatus
- Inherits:
-
EntryAction
- Object
- EntryAction
- Actions::ForemanOpenbolt::PollTaskStatus
- Defined in:
- app/lib/actions/foreman_openbolt/poll_task_status.rb
Constant Summary collapse
- POLL_INTERVAL =
5.seconds
- RETRY_LIMIT =
5 minutes at 5-second intervals
60
Instance Method Summary collapse
- #exception(msg, e) ⇒ Object
- #extract_proxy_error(response) ⇒ Object
- #finish ⇒ Object
- #humanized_input ⇒ Object
- #humanized_name ⇒ Object
- #log(msg, level = :debug) ⇒ Object
-
#plan(job_id, proxy_id) ⇒ Object
Set up the action when it is first scheduled, storing IDs needed to get information from the proxy.
- #poll_and_reschedule ⇒ Object
- #rescue_strategy ⇒ Object
-
#run(event = nil) ⇒ Object
Main execution method that Dynflow will call repeatedly.
Instance Method Details
#exception(msg, e) ⇒ Object
36 37 38 39 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 36 def exception(msg, e) log("#{msg}: #{e.class}: #{e.}", :error) log(e.backtrace.join("\n"), :error) if e.backtrace end |
#extract_proxy_error(response) ⇒ Object
45 46 47 48 49 50 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 45 def extract_proxy_error(response) error_value = response&.dig('error') return nil if error_value.nil? || (error_value.respond_to?(:empty?) && error_value.empty?) error_value.is_a?(Hash) ? error_value['message'] || error_value.to_s : error_value.to_s end |
#finish ⇒ Object
41 42 43 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 41 def finish log("Polling finished for OpenBolt job #{input[:job_id]}") end |
#humanized_input ⇒ Object
152 153 154 155 156 157 158 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 152 def humanized_input proxy_name = ::SmartProxy.find_by(id: input[:proxy_id])&.name || '(unknown)' task_name = ::ForemanOpenbolt::TaskJob.find_by(job_id: input[:job_id])&.task_name parts = ["job #{input[:job_id]} on #{proxy_name}"] parts << "task: #{task_name}" if task_name parts.join(', ') end |
#humanized_name ⇒ Object
148 149 150 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 148 def humanized_name _('Poll OpenBolt task execution status') end |
#log(msg, level = :debug) ⇒ Object
30 31 32 33 34 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 30 def log(msg, level = :debug) output[:log] ||= [] output[:log] << "[#{Time.now.getlocal.strftime('%Y-%m-%d %H:%M:%S')}] [#{level.upcase}] #{msg}" Rails.logger.send(level, msg) end |
#plan(job_id, proxy_id) ⇒ Object
Set up the action when it is first scheduled, storing IDs needed to get information from the proxy.
14 15 16 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 14 def plan(job_id, proxy_id) plan_self(job_id: job_id, proxy_id: proxy_id) end |
#poll_and_reschedule ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 52 def poll_and_reschedule job_id = input[:job_id] task_job = ::ForemanOpenbolt::TaskJob.find_by(job_id: job_id) if task_job.nil? log("TaskJob record not found for job #{job_id}", :error) finish return end if task_job.completed? finish return end # If the smart proxy has been deleted somehow or is unknown, # we can't poll for status, so finish. proxy = ::SmartProxy.find_by(id: input[:proxy_id]) unless proxy log("Smart Proxy with ID #{input[:proxy_id]} not found for OpenBolt job #{job_id}", :error) task_job.update!(status: 'exception') finish return end begin api = ::ProxyAPI::Openbolt.new(url: proxy.url) # Fetch current status status_result = api.job_status(job_id: job_id) proxy_error = extract_proxy_error(status_result) if proxy_error log("Proxy returned error for job #{job_id}: #{proxy_error}", :error) task_job.update!(status: 'exception') finish return end unless status_result&.dig('status') log("Proxy returned response without status for job #{job_id}: #{status_result.inspect}", :error) task_job.update!(status: 'exception') finish return end input[:retry_count] = 0 new_status = status_result['status'] if new_status == task_job.status log("Poll for OpenBolt job #{job_id}: status=#{new_status}") else previous_status = task_job.status task_job.update!(status: new_status) log("OpenBolt job #{job_id} status changed from '#{previous_status}' to '#{new_status}'", :info) end # If completed, fetch full results if task_job.completed? result = api.job_result(job_id: job_id) if result.present? task_job.update_from_proxy_result!(result) log("OpenBolt job #{job_id} completed with status '#{task_job.status}'", :info) else log("No result returned from proxy for completed OpenBolt job #{job_id}", :error) end finish return end # Still running, schedule next poll in 5 seconds suspend do |suspended_action| world.clock.ping(suspended_action, POLL_INTERVAL.from_now.to_time, :poll) end rescue StandardError => e exception("Error polling task status for job #{job_id}", e) retry_count = (input[:retry_count] || 0) + 1 input[:retry_count] = retry_count if retry_count > RETRY_LIMIT log("Polling gave up for job #{job_id} after #{retry_count} attempts", :error) task_job.update!(status: 'exception') finish return end suspend do |suspended_action| world.clock.ping(suspended_action, POLL_INTERVAL.from_now.to_time, :poll) end end end |
#rescue_strategy ⇒ Object
144 145 146 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 144 def rescue_strategy Dynflow::Action::Rescue::Skip end |
#run(event = nil) ⇒ Object
Main execution method that Dynflow will call repeatedly. event = nil when execution starts event = :poll when this is triggered by the timer
21 22 23 24 25 26 27 28 |
# File 'app/lib/actions/foreman_openbolt/poll_task_status.rb', line 21 def run(event = nil) if event.nil? || event.to_sym == :poll poll_and_reschedule else log("Received unknown event '#{event}' for OpenBolt job #{input[:job_id]}", :error) finish end end |