foreman-tasks 0.7.3 → 0.7.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/lib/actions/bulk_action.rb +2 -2
- data/app/lib/actions/entry_action.rb +4 -0
- data/app/lib/actions/middleware/keep_current_user.rb +20 -1
- data/app/lib/actions/proxy_action.rb +106 -19
- data/app/lib/actions/serializers/active_record_serializer.rb +26 -0
- data/app/lib/proxy_api/foreman_dynflow/dynflow_proxy.rb +5 -1
- data/app/models/foreman_tasks/task.rb +3 -1
- data/app/models/foreman_tasks/task/dynflow_task.rb +9 -1
- data/app/models/foreman_tasks/task/summarizer.rb +2 -2
- data/app/models/foreman_tasks/task/task_cancelled_exception.rb +7 -0
- data/app/views/foreman_tasks/tasks/_details.html.erb +14 -2
- data/app/views/foreman_tasks/tasks/index.html.erb +3 -1
- data/db/migrate/20150817102538_add_delay_attributes.rb +6 -0
- data/db/seeds.d/61-foreman_tasks_bookmarks.rb +12 -0
- data/lib/foreman_tasks.rb +5 -0
- data/lib/foreman_tasks/dynflow/persistence.rb +15 -4
- data/lib/foreman_tasks/triggers.rb +4 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +2 -2
- data/test/unit/actions/proxy_action_test.rb +18 -0
- data/test/unit/cleaner_test.rb +1 -1
- data/test/unit/task_test.rb +2 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NzAzZDZlZGRhYjg2OWM2ZGU3NTdkMGMzMmZmMTg4ZDJhODU3NjU3NA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzQ1ZDRmODAwYzg3ODhhNThjMGVmNmQyZDQwNDA3NDliNjVkYjYxNQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
N2U4ZmQ0ZTE4MTZkNDlmMWRmYmEzYThhODJiYWQwZTEyOTQyY2Q3MWZjMzM1
|
10
|
+
NDJlNjQ1YWNjNWU5ODgzZmE3NjVmN2Q0Y2YzMGI4Y2NlZjZkN2RmODcyYzRk
|
11
|
+
ODc5Y2FlNWQ5ZDE3YjlmODYyMWYzYTI3YTljOWIxMTdmOWYwMzE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YTU2ZjFlNTY2ZjI3MzA5ZmMxMWQ2YzQzMDQxMTZjMjY3NDExMjNmNjVlZjkz
|
14
|
+
ZjJhOGRlODk5OTgxOGIyZDI0NzE0YjY3ZmFhZDQxNmE4NGFlYWQ4Y2Q3ZWMw
|
15
|
+
MTY5MWMwNjMzNDVlOWJiMzE2YWZjMTgwZjc0NDZkZjYyNmE2MWY=
|
@@ -54,10 +54,10 @@ module Actions
|
|
54
54
|
|
55
55
|
def check_targets!(targets)
|
56
56
|
if targets.empty?
|
57
|
-
fail
|
57
|
+
fail ::Foreman::Exception.new(N_("Empty bulk action"))
|
58
58
|
end
|
59
59
|
if targets.map(&:class).uniq.length > 1
|
60
|
-
fail
|
60
|
+
fail ::Foreman::Exception.new(N_("The targets are of different types"))
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -15,8 +15,15 @@ module Actions
|
|
15
15
|
module Middleware
|
16
16
|
|
17
17
|
class KeepCurrentUser < Dynflow::Middleware
|
18
|
+
|
19
|
+
def delay(*args)
|
20
|
+
pass(*args).tap { store_current_user }
|
21
|
+
end
|
22
|
+
|
18
23
|
def plan(*args)
|
19
|
-
|
24
|
+
with_current_user do
|
25
|
+
pass(*args).tap { store_current_user }
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
def run(*args)
|
@@ -29,6 +36,18 @@ module Actions
|
|
29
36
|
|
30
37
|
private
|
31
38
|
|
39
|
+
def with_current_user
|
40
|
+
if User.current || action.input[:current_user_id].nil?
|
41
|
+
yield
|
42
|
+
else
|
43
|
+
restore_curent_user { yield }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def store_current_user
|
48
|
+
action.input[:current_user_id] = User.current.try(:id)
|
49
|
+
end
|
50
|
+
|
32
51
|
def restore_curent_user
|
33
52
|
User.current = User.find(action.input[:current_user_id])
|
34
53
|
yield
|
@@ -2,6 +2,7 @@ module Actions
|
|
2
2
|
class ProxyAction < Base
|
3
3
|
|
4
4
|
include ::Dynflow::Action::Cancellable
|
5
|
+
include ::Dynflow::Action::Timeouts
|
5
6
|
|
6
7
|
class CallbackData
|
7
8
|
attr_reader :data
|
@@ -12,39 +13,65 @@ module Actions
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def plan(proxy, options)
|
16
|
+
options[:connection_options] ||= {}
|
17
|
+
default_connection_options.each { |key, value| options[:connection_options][key] ||= value }
|
15
18
|
plan_self(options.merge(:proxy_url => proxy.url))
|
16
19
|
end
|
17
20
|
|
18
21
|
def run(event = nil)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
with_connection_error_handling(event) do |event|
|
23
|
+
case event
|
24
|
+
when nil
|
25
|
+
if output[:proxy_task_id]
|
26
|
+
on_resume
|
27
|
+
else
|
28
|
+
trigger_proxy_task
|
29
|
+
end
|
30
|
+
suspend
|
31
|
+
when ::Dynflow::Action::Skip
|
32
|
+
# do nothing
|
33
|
+
when ::Dynflow::Action::Cancellable::Cancel
|
34
|
+
cancel_proxy_task
|
35
|
+
when CallbackData
|
36
|
+
on_data(event.data)
|
37
|
+
when ::Dynflow::Action::Timeouts::Timeout
|
38
|
+
check_task_status
|
23
39
|
else
|
24
|
-
|
40
|
+
raise "Unexpected event #{event.inspect}"
|
25
41
|
end
|
26
|
-
suspend
|
27
|
-
when ::Dynflow::Action::Skip
|
28
|
-
# do nothing
|
29
|
-
when ::Dynflow::Action::Cancellable::Cancel
|
30
|
-
cancel_proxy_task
|
31
|
-
when CallbackData
|
32
|
-
on_data(event.data)
|
33
|
-
else
|
34
|
-
raise "Unexpected event #{event.inspect}"
|
35
42
|
end
|
36
43
|
end
|
37
44
|
|
38
45
|
def trigger_proxy_task
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
suspend do |_suspended_action|
|
47
|
+
set_timeout! unless timeout_set?
|
48
|
+
response = proxy.trigger_task(proxy_action_name,
|
49
|
+
input.merge(:callback => { :task_id => task.id,
|
50
|
+
:step_id => run_step_id }))
|
51
|
+
output[:proxy_task_id] = response["task_id"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_task_status
|
56
|
+
if output[:proxy_task_id]
|
57
|
+
response = proxy.status_of_task(output[:proxy_task_id])
|
58
|
+
if response['state'] == 'stopped'
|
59
|
+
if response['result'] == 'error'
|
60
|
+
raise ::Foreman::Exception, _("The smart proxy task '#{output[:proxy_task_id]}' failed.")
|
61
|
+
else
|
62
|
+
on_data(response['actions'].find { |block_action| block_action['class'] == proxy_action_name }['output'])
|
63
|
+
end
|
64
|
+
else
|
65
|
+
cancel_proxy_task
|
66
|
+
end
|
67
|
+
else
|
68
|
+
process_timeout
|
69
|
+
end
|
43
70
|
end
|
44
71
|
|
45
72
|
def cancel_proxy_task
|
46
73
|
if output[:cancel_sent]
|
47
|
-
error! _("Cancel enforced: the task might be still running on the proxy")
|
74
|
+
error! ForemanTasks::Task::TaskCancelledException.new(_("Cancel enforced: the task might be still running on the proxy"))
|
48
75
|
else
|
49
76
|
proxy.cancel_task(output[:proxy_task_id])
|
50
77
|
output[:cancel_sent] = true
|
@@ -78,5 +105,65 @@ module Actions
|
|
78
105
|
def proxy_output=(output)
|
79
106
|
output[:proxy_output] = output
|
80
107
|
end
|
108
|
+
|
109
|
+
def metadata
|
110
|
+
output[:metadata] ||= {}
|
111
|
+
output[:metadata]
|
112
|
+
end
|
113
|
+
|
114
|
+
def metadata=(thing)
|
115
|
+
output[:metadata] ||= {}
|
116
|
+
output[:metadata] = thing
|
117
|
+
end
|
118
|
+
|
119
|
+
def timeout_set?
|
120
|
+
!metadata[:timeout].nil?
|
121
|
+
end
|
122
|
+
|
123
|
+
def set_timeout!
|
124
|
+
time = Time.now + input[:connection_options][:timeout]
|
125
|
+
schedule_timeout(time)
|
126
|
+
metadata[:timeout] = time.to_s
|
127
|
+
end
|
128
|
+
|
129
|
+
def default_connection_options
|
130
|
+
# Fails if the plan is not finished within 60 seconds from the first task trigger attempt on the smart proxy
|
131
|
+
# If the triggering fails, it retries 3 more times with 15 second delays
|
132
|
+
{ :retry_interval => 15, :retry_count => 4, :timeout => 60 }
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def with_connection_error_handling(event = nil)
|
138
|
+
yield event
|
139
|
+
rescue ::RestClient::Exception, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT => e
|
140
|
+
if event.class == CallbackData || event == ::Dynflow::Action::Timeouts::Timeout
|
141
|
+
raise e
|
142
|
+
else
|
143
|
+
handle_connection_exception(e, event)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def format_exception(exception)
|
148
|
+
{ output[:proxy_task_id] =>
|
149
|
+
{ :exception_class => exception.class.name,
|
150
|
+
:execption_message => exception.message } }
|
151
|
+
end
|
152
|
+
|
153
|
+
def handle_connection_exception(exception, event = nil)
|
154
|
+
metadata[:failed_proxy_tasks] ||= []
|
155
|
+
options = input[:connection_options]
|
156
|
+
metadata[:failed_proxy_tasks] << format_exception(exception)
|
157
|
+
output[:proxy_task_id] = nil
|
158
|
+
if metadata[:failed_proxy_tasks].count < options[:retry_count]
|
159
|
+
suspend do |suspended_action|
|
160
|
+
@world.clock.ping suspended_action,
|
161
|
+
Time.now + options[:retry_interval],
|
162
|
+
event
|
163
|
+
end
|
164
|
+
else
|
165
|
+
raise exception
|
166
|
+
end
|
167
|
+
end
|
81
168
|
end
|
82
169
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Actions
|
2
|
+
module Serializers
|
3
|
+
|
4
|
+
class ActiveRecordSerializer < ::Dynflow::Serializers::Noop
|
5
|
+
def serialize(arg)
|
6
|
+
if arg.is_a? ActiveRecord::Base
|
7
|
+
{ :active_record_object => true,
|
8
|
+
:class_name => arg.class.name,
|
9
|
+
:id => arg.id }
|
10
|
+
else
|
11
|
+
super arg
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def deserialize(arg)
|
16
|
+
if arg.is_a?(Hash) && arg[:active_record_object]
|
17
|
+
arg[:class_name].constantize.find(arg[:id])
|
18
|
+
else
|
19
|
+
super arg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -22,10 +22,14 @@ module ProxyAPI
|
|
22
22
|
MultiJson.load(Task.new(@args).send(:post, payload))
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# Cancel the command
|
26
26
|
def cancel_task(proxy_task_id)
|
27
27
|
MultiJson.load(Task.new(@args).send(:post, "", "#{ proxy_task_id }/cancel"))
|
28
28
|
end
|
29
|
+
|
30
|
+
def status_of_task(proxy_task_id)
|
31
|
+
MultiJson.load(Task.new(@args).send(:get, "#{ proxy_task_id }/status"))
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -23,6 +23,7 @@ module ForemanTasks
|
|
23
23
|
scoped_search :on => :state, :complete_value => true
|
24
24
|
scoped_search :on => :result, :complete_value => true
|
25
25
|
scoped_search :on => :started_at, :complete_value => false
|
26
|
+
scoped_search :on => :ended_at, :complete_value => false
|
26
27
|
scoped_search :on => :parent_task_id, :complete_value => true
|
27
28
|
scoped_search :in => :locks, :on => :resource_type, :complete_value => true, :rename => "resource_type", :ext_method => :search_by_generic_resource
|
28
29
|
scoped_search :in => :locks, :on => :resource_id, :complete_value => false, :rename => "resource_id", :ext_method => :search_by_generic_resource
|
@@ -66,9 +67,10 @@ module ForemanTasks
|
|
66
67
|
end
|
67
68
|
|
68
69
|
# returns true if the task is running or waiting to be run
|
69
|
-
def pending
|
70
|
+
def pending?
|
70
71
|
self.state != 'stopped'
|
71
72
|
end
|
73
|
+
alias_method :pending, :pending?
|
72
74
|
|
73
75
|
def resumable?
|
74
76
|
false
|
@@ -11,6 +11,8 @@ module ForemanTasks
|
|
11
11
|
self.ended_at = data[:ended_at]
|
12
12
|
self.state = data[:state].to_s
|
13
13
|
self.result = data[:result].to_s
|
14
|
+
self.start_at = data[:start_at] if data[:start_at]
|
15
|
+
self.start_before = data[:start_before] if data[:start_before]
|
14
16
|
self.parent_task_id ||= begin
|
15
17
|
if main_action.caller_execution_plan_id
|
16
18
|
DynflowTask.find_by_external_id!(main_action.caller_execution_plan_id).id
|
@@ -102,10 +104,16 @@ module ForemanTasks
|
|
102
104
|
logger.warn("Task %s updated at consistency check: %s" % [task.id, changes.inspect])
|
103
105
|
end
|
104
106
|
rescue => e
|
105
|
-
Foreman::Logging.exception("Failed at consistency check for task #{task.id}", e, :logger =>
|
107
|
+
Foreman::Logging.exception("Failed at consistency check for task #{task.id}", e, :logger => 'foreman-tasks')
|
106
108
|
end
|
107
109
|
end
|
108
110
|
return fixed_count
|
109
111
|
end
|
112
|
+
|
113
|
+
def self.new_for_execution_plan(execution_plan_id, data)
|
114
|
+
self.new(:external_id => execution_plan_id,
|
115
|
+
:state => data[:state].to_s,
|
116
|
+
:result => data[:result].to_s)
|
117
|
+
end
|
110
118
|
end
|
111
119
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ForemanTasks
|
2
2
|
class Task::Summarizer
|
3
3
|
def summarize_by_status(since=nil)
|
4
|
-
result = ::ForemanTasks::Task.select('count(state), state, result').group(:state, :result).order(:state)
|
5
|
-
result.where('started_at > ?', since) if since
|
4
|
+
result = ::ForemanTasks::Task.select('count(state) AS count, state, result').group(:state, :result).order(:state)
|
5
|
+
result = result.where('started_at > ?', since) if since
|
6
6
|
result
|
7
7
|
end
|
8
8
|
|
@@ -95,13 +95,25 @@
|
|
95
95
|
<span class="param-name"><%= _("Owner") %>:</span>
|
96
96
|
<span class="param-value"><%= @task.username %></span>
|
97
97
|
</div>
|
98
|
+
<div>
|
99
|
+
<span class="param-name"><%= _("Execution type") %>:</span>
|
100
|
+
<span class="param-value"><%= @task.start_at.nil? ? _('Immediate') : _('Delayed') %></span>
|
101
|
+
</div>
|
102
|
+
<div>
|
103
|
+
<span class="param-name"><%= _("Start at") %>:</span>
|
104
|
+
<span class="param-value"><%= @task.start_at.nil? ? '-' : @task.start_at %></span>
|
105
|
+
</div>
|
106
|
+
<div>
|
107
|
+
<span class="param-name"><%= _("Start before") %>:</span>
|
108
|
+
<span class="param-value"><%= @task.start_before.nil? ? '-' : @task.start_before %></span>
|
109
|
+
</div>
|
98
110
|
<div>
|
99
111
|
<span class="param-name"><%= _("Started at") %>:</span>
|
100
|
-
<span class="param-value"><%= @task.started_at %></span>
|
112
|
+
<span class="param-value"><%= @task.started_at.try(:in_time_zone) %></span>
|
101
113
|
</div>
|
102
114
|
<div>
|
103
115
|
<span class="param-name"><%= _("Ended at") %>:</span>
|
104
|
-
<span class="param-value"><%= @task.ended_at %></span>
|
116
|
+
<span class="param-value"><%= @task.ended_at.try(:in_time_zone) %></span>
|
105
117
|
</div>
|
106
118
|
<div>
|
107
119
|
<span class="param-name"><%= _("State") %>:</span>
|
@@ -32,6 +32,7 @@ $(document).on('click', ".table-two-pane td.two-pane-link", function(e) {
|
|
32
32
|
<th><%= _("State") %></th>
|
33
33
|
<th><%= _("Result") %></th>
|
34
34
|
<th><%= sort :started_at, :as => _("Started at") %></th>
|
35
|
+
<th><%= sort :ended_at, :as => _("Ended at") %></th>
|
35
36
|
<th><%= _("User") %></th>
|
36
37
|
</tr>
|
37
38
|
<% for task in @tasks %>
|
@@ -42,7 +43,8 @@ $(document).on('click', ".table-two-pane td.two-pane-link", function(e) {
|
|
42
43
|
</td>
|
43
44
|
<td><%= task.state %></td>
|
44
45
|
<td><%= task.result %></td>
|
45
|
-
<td><%= task.started_at %></td>
|
46
|
+
<td><%= task.started_at.try(:in_time_zone) %></td>
|
47
|
+
<td><%= task.ended_at.try(:in_time_zone) %></td>
|
46
48
|
<td><%= task.username %></td>
|
47
49
|
</tr>
|
48
50
|
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Bookmark.without_auditing do
|
2
|
+
[
|
3
|
+
{ :name => "running", :query => "state = running" },
|
4
|
+
{ :name => "failed", :query => "state = paused or result = error or result = warning" }
|
5
|
+
|
6
|
+
].each do |item|
|
7
|
+
next if Bookmark.find_by_name(item[:name])
|
8
|
+
next if audit_modified? Bookmark, item[:name]
|
9
|
+
b = Bookmark.create({:controller => "foreman_tasks_tasks", :public => true}.merge(item))
|
10
|
+
raise "Unable to create bookmark: #{format_errors b}" if b.nil? || b.errors.any?
|
11
|
+
end
|
12
|
+
end
|
data/lib/foreman_tasks.rb
CHANGED
@@ -40,4 +40,9 @@ module ForemanTasks
|
|
40
40
|
raise TaskError.new(task) if task.execution_plan.error?
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
def self.delay(action, delay_options, *args)
|
45
|
+
result = dynflow.world.delay action, delay_options, *args
|
46
|
+
ForemanTasks::Task::DynflowTask.find_by_external_id!(result.id)
|
47
|
+
end
|
43
48
|
end
|
@@ -13,7 +13,7 @@ module ForemanTasks
|
|
13
13
|
begin
|
14
14
|
on_execution_plan_save(execution_plan_id, value)
|
15
15
|
rescue => e
|
16
|
-
Foreman::Logging.exception("Error on on_execution_plan_save event", e, :logger =>
|
16
|
+
Foreman::Logging.exception("Error on on_execution_plan_save event", e, :logger => 'foreman-tasks/dynflow')
|
17
17
|
end
|
18
18
|
end
|
19
19
|
ensure
|
@@ -23,11 +23,22 @@ module ForemanTasks
|
|
23
23
|
def on_execution_plan_save(execution_plan_id, data)
|
24
24
|
# We can load the data unless the execution plan was properly planned and saved
|
25
25
|
# including its steps
|
26
|
-
|
27
|
-
|
26
|
+
case data[:state]
|
27
|
+
when :pending
|
28
|
+
ForemanTasks::Task::DynflowTask.new_for_execution_plan(execution_plan_id, data).save!
|
29
|
+
when :scheduled
|
30
|
+
delayed_plan = load_delayed_plan(execution_plan_id)
|
31
|
+
raise Foreman::Exception.new('Plan is delayed but the delay record is missing') if delayed_plan.nil?
|
32
|
+
# TODO: Rework this
|
33
|
+
delayed_plan = ::Dynflow::DelayedPlan.new_from_hash(ForemanTasks.dynflow.world, delayed_plan)
|
34
|
+
task = ::ForemanTasks::Task::DynflowTask.find_by_external_id(execution_plan_id)
|
35
|
+
task.update_from_dynflow(data.merge(:start_at => delayed_plan.start_at,
|
36
|
+
:start_before => delayed_plan.start_before))
|
37
|
+
when :planning
|
38
|
+
task = ::ForemanTasks::Task::DynflowTask.find_by_external_id(execution_plan_id)
|
28
39
|
task.update_from_dynflow(data)
|
29
40
|
Lock.owner!(::User.current, task.id) if ::User.current
|
30
|
-
|
41
|
+
else
|
31
42
|
if task = ::ForemanTasks::Task::DynflowTask.find_by_external_id(execution_plan_id)
|
32
43
|
unless task.state.to_s == data[:state].to_s
|
33
44
|
task.update_from_dynflow(data)
|
@@ -40,8 +40,8 @@ module ForemanTasks
|
|
40
40
|
task.reload
|
41
41
|
task.state.must_equal 'stopped'
|
42
42
|
task.result.must_equal 'success'
|
43
|
-
task.main_action.output.must_equal
|
44
|
-
|
43
|
+
task.main_action.output['proxy_task_id'].must_equal "123"
|
44
|
+
task.main_action.output['proxy_output'].must_equal({ 'result' => 'success' })
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -17,6 +17,7 @@ module ForemanTasks
|
|
17
17
|
proxy_call = Support::DummyProxyAction.proxy.log[:trigger_task].first
|
18
18
|
proxy_call.must_equal(["Proxy::DummyAction",
|
19
19
|
{ "foo" => "bar",
|
20
|
+
"connection_options" => { "retry_interval" => 15, "retry_count" => 4, "timeout" => 60 },
|
20
21
|
"proxy_url" => "proxy.example.com",
|
21
22
|
"callback" => { "task_id" => "123", "step_id" => @action.run_step_id }}])
|
22
23
|
end
|
@@ -61,6 +62,23 @@ module ForemanTasks
|
|
61
62
|
action = run_action(@action, ::Actions::ProxyAction::CallbackData.new('result' => 'success'))
|
62
63
|
action.output[:proxy_output].must_equal({'result' => 'success'})
|
63
64
|
end
|
65
|
+
|
66
|
+
it 'handles connection errors' do
|
67
|
+
action = create_and_plan_action(Support::DummyProxyAction, Support::DummyProxyAction.proxy, { :foo => 'bar' })
|
68
|
+
run_stubbed_action = lambda do |lambda_action|
|
69
|
+
run_action lambda_action do |block_action|
|
70
|
+
block_action.expects(:trigger_proxy_task).raises(Errno::ECONNREFUSED.new('Connection refused'))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
action = run_stubbed_action.call action
|
74
|
+
action.state.must_equal :suspended
|
75
|
+
action.world.clock.pending_pings.length.must_equal 1
|
76
|
+
action.output[:metadata][:failed_proxy_tasks].length.must_equal 1
|
77
|
+
2.times { action.output[:metadata][:failed_proxy_tasks] << {} }
|
78
|
+
proc { action = run_stubbed_action.call action }.must_raise(Errno::ECONNREFUSED)
|
79
|
+
action.state.must_equal :error
|
80
|
+
end
|
81
|
+
|
64
82
|
end
|
65
83
|
|
66
84
|
end
|
data/test/unit/cleaner_test.rb
CHANGED
@@ -14,7 +14,7 @@ class TasksTest < ActiveSupport::TestCase
|
|
14
14
|
FactoryGirl.create(:dynflow_task, :product_create_task)]
|
15
15
|
cleaner.delete
|
16
16
|
ForemanTasks::Task.where(id: tasks_to_delete).must_be_empty
|
17
|
-
ForemanTasks::Task.where(id: tasks_to_keep).must_equal tasks_to_keep
|
17
|
+
ForemanTasks::Task.where(id: tasks_to_keep).order(:id).map(&:id).must_equal tasks_to_keep.map(&:id).sort
|
18
18
|
|
19
19
|
ForemanTasks.dynflow.world.persistence.
|
20
20
|
find_execution_plans(filters: {'uuid' => tasks_to_delete.map(&:external_id)}).size.must_equal 0
|
data/test/unit/task_test.rb
CHANGED
@@ -41,12 +41,13 @@ class TasksTest < ActiveSupport::TestCase
|
|
41
41
|
let(:inconsistent_task) { FactoryGirl.create(:dynflow_task, :inconsistent_dynflow_task) }
|
42
42
|
|
43
43
|
it 'ensures the tasks marked as running are really running in Dynflow' do
|
44
|
+
running_task_count = ForemanTasks::Task::DynflowTask.running.count
|
44
45
|
consistent_task.state.must_equal 'planned'
|
45
46
|
inconsistent_task.state.must_equal 'running'
|
46
47
|
|
47
48
|
fixed_count = ForemanTasks::Task::DynflowTask.consistency_check
|
48
49
|
|
49
|
-
fixed_count.must_equal 1
|
50
|
+
fixed_count.must_equal running_task_count + 1
|
50
51
|
consistent_task.reload.state.must_equal 'planned'
|
51
52
|
inconsistent_task.reload.state.must_equal 'planned'
|
52
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.8.
|
19
|
+
version: 0.8.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.8.
|
26
|
+
version: 0.8.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sequel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- app/lib/actions/helpers/lock.rb
|
106
106
|
- app/lib/actions/middleware/keep_current_user.rb
|
107
107
|
- app/lib/actions/proxy_action.rb
|
108
|
+
- app/lib/actions/serializers/active_record_serializer.rb
|
108
109
|
- app/lib/proxy_api/foreman_dynflow/dynflow_proxy.rb
|
109
110
|
- app/models/foreman_tasks/concerns/action_subject.rb
|
110
111
|
- app/models/foreman_tasks/concerns/action_triggering.rb
|
@@ -115,6 +116,7 @@ files:
|
|
115
116
|
- app/models/foreman_tasks/task/dynflow_task.rb
|
116
117
|
- app/models/foreman_tasks/task/status_explicator.rb
|
117
118
|
- app/models/foreman_tasks/task/summarizer.rb
|
119
|
+
- app/models/foreman_tasks/task/task_cancelled_exception.rb
|
118
120
|
- app/models/setting/foreman_tasks.rb
|
119
121
|
- app/views/foreman_tasks/api/tasks/show.json.rabl
|
120
122
|
- app/views/foreman_tasks/tasks/_details.html.erb
|
@@ -134,8 +136,10 @@ files:
|
|
134
136
|
- db/migrate/20131209122644_create_foreman_tasks_locks.rb
|
135
137
|
- db/migrate/20140324104010_remove_foreman_tasks_progress.rb
|
136
138
|
- db/migrate/20140813215942_add_parent_task_id.rb
|
139
|
+
- db/migrate/20150817102538_add_delay_attributes.rb
|
137
140
|
- db/seeds.d/20-foreman_tasks_permissions.rb
|
138
141
|
- db/seeds.d/60-dynflow_proxy_feature.rb
|
142
|
+
- db/seeds.d/61-foreman_tasks_bookmarks.rb
|
139
143
|
- deploy/foreman-tasks.init
|
140
144
|
- deploy/foreman-tasks.service
|
141
145
|
- deploy/foreman-tasks.sysconfig
|