Class: ForemanTasks::Task

Inherits:
ApplicationRecord
  • Object
show all
Extended by:
Search
Includes:
Authorizable
Defined in:
app/models/foreman_tasks/task.rb,
app/models/foreman_tasks/task/search.rb

Direct Known Subclasses

DynflowTask

Defined Under Namespace

Modules: Search Classes: DynflowTask, Jail, StatusExplicator, Summarizer, TaskCancelledException

Constant Summary

Constants included from Search

Search::SUPPORTED_DURATION_FORMAT

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Search

search_by_duration, search_by_generic_resource, search_by_taxonomy

Class Method Details

.authorized_resource_nameObject



206
207
208
209
# File 'app/models/foreman_tasks/task.rb', line 206

def self.authorized_resource_name
  # We don't want STI subclasses to have separate permissions
  'ForemanTasks::Task'
end

.latest_tasks_by_resource_ids(label, resource_type, resource_ids) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'app/models/foreman_tasks/task.rb', line 261

def self.latest_tasks_by_resource_ids(label, resource_type, resource_ids)
  tasks = arel_table
  links = ForemanTasks::Link.arel_table
  started_at = tasks[:started_at]
  resource_id = links[:resource_id]

  base_combined_table = tasks
                        .join(links).on(tasks[:id].eq(links[:task_id]))
                        .where(tasks[:label].eq(label)
                                            .and(links[:resource_type].eq(resource_type))
                                            .and(links[:resource_id].in(resource_ids)))

  grouped = base_combined_table.project(
    started_at.maximum.as('started_at_max'),
    resource_id
  ).group(resource_id).order(resource_id).as('grouped')

  max_per_resource_id = tasks
                        .join(links).on(tasks[:id].eq(links[:task_id]))
                        .join(grouped).on(grouped[:started_at_max].eq(started_at).and(grouped[:resource_id].eq(resource_id)))
                        .distinct
                        .project(tasks[Arel.star], grouped[:resource_id])

  find_by_sql(max_per_resource_id.to_sql).index_by(&:resource_id)
end

Instance Method Details

#actionObject



237
238
239
240
# File 'app/models/foreman_tasks/task.rb', line 237

def action
  return to_label if super.blank?
  super
end

#action_continuous_outputObject



255
256
257
258
259
# File 'app/models/foreman_tasks/task.rb', line 255

def action_continuous_output
  return unless main_action.is_a?(Actions::Helpers::WithContinuousOutput)
  main_action.continuous_output.sort!
  main_action.continuous_output.raw_outputs
end

#add_missing_task_groups(groups) ⇒ Object



211
212
213
214
215
# File 'app/models/foreman_tasks/task.rb', line 211

def add_missing_task_groups(groups)
  groups = [groups] unless groups.is_a? Array
  (groups - task_groups).each { |group| task_groups << group }
  save!
end

#build_notificationsObject



183
184
185
186
187
188
189
190
191
192
193
# File 'app/models/foreman_tasks/task.rb', line 183

def build_notifications
  notifications = []
  if paused?
    owner = self.owner
    if owner && !owner.hidden?
      notifications << UINotifications::Tasks::TaskPausedOwner.new(self)
    end
    notifications << UINotifications::Tasks::TaskPausedAdmin.new(self)
  end
  notifications
end

#check_permissions_after_saveObject



10
11
12
13
14
15
# File 'app/models/foreman_tasks/task.rb', line 10

def check_permissions_after_save
  # there's no create_tasks permission, tasks are created as a result of internal actions, in such case we
  # don't do authorization, that should have been performed on wrapping action level
  # the same applies for updating
  true
end

#cli_exampleObject



140
141
142
# File 'app/models/foreman_tasks/task.rb', line 140

def cli_example
  ''
end

#delayed?Boolean

returns true if the task was planned to execute in the future

Returns:

  • (Boolean)


168
169
170
# File 'app/models/foreman_tasks/task.rb', line 168

def delayed?
  start_at.to_i != started_at.to_i
end

#execution_typeObject



114
115
116
# File 'app/models/foreman_tasks/task.rb', line 114

def execution_type
  delayed? ? N_('Delayed') : N_('Immediate')
end

#get_humanized(method) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/foreman_tasks/task.rb', line 118

def get_humanized(method)
  attr = case method
         when :humanized_name
           :action
         when :humanized_input
           :input
         when :humanized_output
           :output
         end
  if attr
    humanized[attr]
  else
    _('N/A')
  end
end

#humanizedObject



134
135
136
137
138
# File 'app/models/foreman_tasks/task.rb', line 134

def humanized
  { action: action,
    input:  '',
    output: '' }
end

#inputObject



98
99
100
# File 'app/models/foreman_tasks/task.rb', line 98

def input
  {}
end

#notification_recipients_idsObject

used by Foreman notifications framework



179
180
181
# File 'app/models/foreman_tasks/task.rb', line 179

def notification_recipients_ids
  [owner.id]
end

#outputObject



102
103
104
# File 'app/models/foreman_tasks/task.rb', line 102

def output
  {}
end

#ownerObject



106
107
108
# File 'app/models/foreman_tasks/task.rb', line 106

def owner
  user
end

#paused?Boolean

Returns:

  • (Boolean)


154
155
156
# File 'app/models/foreman_tasks/task.rb', line 154

def paused?
  state == 'paused'
end

#pending?Boolean Also known as: pending

returns true if the task is running or waiting to be run

Returns:

  • (Boolean)


145
146
147
# File 'app/models/foreman_tasks/task.rb', line 145

def pending?
  state != 'stopped'
end

#progressObject



195
196
197
198
199
200
201
202
203
204
# File 'app/models/foreman_tasks/task.rb', line 195

def progress
  case state.to_s
  when 'running', 'paused'
    0.5
  when 'stopped'
    1
  else
    0
  end
end

#recurring?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'app/models/foreman_tasks/task.rb', line 163

def recurring?
  !recurring_logic_task_group_ids.empty?
end

#resumable?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'app/models/foreman_tasks/task.rb', line 150

def resumable?
  false
end

#scheduled?Boolean

returns true if the task is CURRENTLY waiting to be executed in the future

Returns:

  • (Boolean)


159
160
161
# File 'app/models/foreman_tasks/task.rb', line 159

def scheduled?
  state == 'scheduled'
end

#self_and_parentsObject



172
173
174
175
176
# File 'app/models/foreman_tasks/task.rb', line 172

def self_and_parents
  [self].tap do |ret|
    ret.concat(parent_task.self_and_parents) if parent_task
  end
end

#sub_tasks_countsObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'app/models/foreman_tasks/task.rb', line 217

def sub_tasks_counts
  result = %w[cancelled error pending success warning].inject({}) do |hash, state|
    hash.update(state => 0)
  end
  result.update sub_tasks.group(:result).count
  sum = result.values.reduce(:+)
  if respond_to?(:main_action) && main_action.respond_to?(:total_count)
    result[:total] = main_action.total_count
    # In case of batch planning there might be some plans still unplanned (not present in database).
    # To get correct counts we need to add them to either:
    #   cancelled when the parent is stopped
    #   pending when the parent is still running.
    key = state == 'stopped' ? 'cancelled' : 'pending'
    result[key] += result[:total] - sum
  else
    result[:total] = sum
  end
  result.symbolize_keys
end

#to_labelObject



242
243
244
245
246
247
248
249
250
251
252
253
# File 'app/models/foreman_tasks/task.rb', line 242

def to_label
  parts = []
  parts << get_humanized(:name)
  parts << Array(get_humanized(:input)).map do |part|
    if part.is_a? Array
      part[1][:text]
    else
      part.to_s
    end
  end.join('; ')
  parts.join(' ').strip
end

#usernameObject



110
111
112
# File 'app/models/foreman_tasks/task.rb', line 110

def username
  owner.try(:login)
end