foreman-tasks 0.8.6 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +35 -0
  3. data/.rubocop_todo.yml +138 -0
  4. data/app/controllers/foreman_tasks/api/recurring_logics_controller.rb +3 -4
  5. data/app/controllers/foreman_tasks/api/tasks_controller.rb +56 -72
  6. data/app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb +2 -4
  7. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +2 -5
  8. data/app/controllers/foreman_tasks/tasks_controller.rb +7 -8
  9. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +44 -46
  10. data/app/helpers/foreman_tasks/tasks_helper.rb +1 -1
  11. data/app/lib/actions/action_with_sub_plans.rb +6 -8
  12. data/app/lib/actions/base.rb +6 -7
  13. data/app/lib/actions/bulk_action.rb +13 -9
  14. data/app/lib/actions/entry_action.rb +1 -3
  15. data/app/lib/actions/foreman/host/import_facts.rb +2 -5
  16. data/app/lib/actions/foreman/puppetclass/import.rb +1 -1
  17. data/app/lib/actions/helpers/args_serialization.rb +0 -1
  18. data/app/lib/actions/helpers/humanizer.rb +16 -21
  19. data/app/lib/actions/helpers/with_continuous_output.rb +0 -1
  20. data/app/lib/actions/helpers/with_delegated_action.rb +2 -2
  21. data/app/lib/actions/middleware/inherit_task_groups.rb +3 -5
  22. data/app/lib/actions/middleware/keep_current_user.rb +0 -3
  23. data/app/lib/actions/middleware/recurring_logic.rb +0 -1
  24. data/app/lib/actions/proxy_action.rb +8 -8
  25. data/app/lib/actions/serializers/active_record_serializer.rb +0 -3
  26. data/app/lib/proxy_api/foreman_dynflow/dynflow_proxy.rb +3 -3
  27. data/app/models/foreman_tasks/concerns/action_subject.rb +4 -6
  28. data/app/models/foreman_tasks/concerns/action_triggering.rb +20 -33
  29. data/app/models/foreman_tasks/concerns/host_action_subject.rb +5 -5
  30. data/app/models/foreman_tasks/lock.rb +29 -37
  31. data/app/models/foreman_tasks/recurring_logic.rb +23 -24
  32. data/app/models/foreman_tasks/task.rb +65 -39
  33. data/app/models/foreman_tasks/task/dynflow_task.rb +23 -24
  34. data/app/models/foreman_tasks/task/status_explicator.rb +3 -3
  35. data/app/models/foreman_tasks/task/summarizer.rb +3 -3
  36. data/app/models/foreman_tasks/task_group.rb +0 -2
  37. data/app/models/foreman_tasks/task_group_member.rb +0 -2
  38. data/app/models/foreman_tasks/task_groups/recurring_logic_task_group.rb +1 -4
  39. data/app/models/foreman_tasks/triggering.rb +19 -19
  40. data/app/models/setting/foreman_tasks.rb +8 -11
  41. data/app/services/foreman_tasks/proxy_selector.rb +4 -5
  42. data/app/views/foreman_tasks/tasks/_details.html.erb +1 -1
  43. data/bin/dynflow-executor +1 -1
  44. data/bin/foreman-tasks +1 -1
  45. data/config/routes.rb +1 -1
  46. data/db/migrate/20150814204140_add_task_type_value_index.rb +1 -1
  47. data/db/migrate/20160924213030_change_tasks_widget_names.rb +8 -8
  48. data/db/seeds.d/61-foreman_tasks_bookmarks.rb +3 -3
  49. data/deploy/foreman-tasks.sysconfig +6 -0
  50. data/extra/dynflow-debug.sh +12 -0
  51. data/foreman-tasks.gemspec +1 -1
  52. data/lib/foreman_tasks.rb +3 -3
  53. data/lib/foreman_tasks/authorizer_ext.rb +1 -1
  54. data/lib/foreman_tasks/cleaner.rb +14 -16
  55. data/lib/foreman_tasks/dynflow.rb +11 -9
  56. data/lib/foreman_tasks/dynflow/configuration.rb +8 -10
  57. data/lib/foreman_tasks/dynflow/console_authorizer.rb +4 -5
  58. data/lib/foreman_tasks/dynflow/daemon.rb +17 -19
  59. data/lib/foreman_tasks/dynflow/persistence.rb +5 -8
  60. data/lib/foreman_tasks/engine.rb +30 -31
  61. data/lib/foreman_tasks/task_error.rb +1 -3
  62. data/lib/foreman_tasks/tasks/cleanup.rake +7 -19
  63. data/lib/foreman_tasks/tasks/dynflow.rake +1 -1
  64. data/lib/foreman_tasks/tasks/export_tasks.rake +51 -59
  65. data/lib/foreman_tasks/test_extensions.rb +1 -1
  66. data/lib/foreman_tasks/version.rb +1 -1
  67. data/lib/tasks/gettext.rake +10 -7
  68. data/locale/action_names.rb +3 -6
  69. data/locale/en/foreman_tasks.po +189 -177
  70. data/locale/foreman_tasks.pot +177 -137
  71. data/test/controllers/api/recurring_logics_controller_test.rb +3 -5
  72. data/test/controllers/api/tasks_controller_test.rb +5 -7
  73. data/test/factories/task_factory.rb +8 -8
  74. data/test/factories/triggering_factory.rb +2 -3
  75. data/test/helpers/foreman_tasks/tasks_helper_test.rb +11 -11
  76. data/test/support/dummy_proxy_action.rb +3 -4
  77. data/test/unit/actions/action_with_sub_plans_test.rb +5 -6
  78. data/test/unit/actions/proxy_action_test.rb +5 -8
  79. data/test/unit/cleaner_test.rb +11 -12
  80. data/test/unit/dynflow_console_authorizer_test.rb +4 -4
  81. data/test/unit/proxy_selector_test.rb +3 -3
  82. data/test/unit/recurring_logic_test.rb +19 -17
  83. data/test/unit/task_groups_test.rb +3 -4
  84. data/test/unit/task_test.rb +72 -5
  85. data/test/unit/triggering_test.rb +0 -1
  86. metadata +7 -6
  87. data/app/controllers/foreman_tasks/concerns/environments_extension.rb +0 -24
@@ -15,7 +15,7 @@ module Actions
15
15
  end
16
16
 
17
17
  def humanized_name
18
- _("Import Puppet classes")
18
+ _('Import Puppet classes')
19
19
  end
20
20
 
21
21
  # default value for cleaning up the tasks, it can be overriden by settings
@@ -62,4 +62,3 @@ module Actions
62
62
  end
63
63
  end
64
64
  end
65
-
@@ -1,8 +1,6 @@
1
1
  module Actions
2
2
  module Helpers
3
-
4
3
  class Humanizer
5
-
6
4
  def initialize(action)
7
5
  @action = action
8
6
  @input = action.respond_to?(:task_input) ? action.task_input : action.input
@@ -20,7 +18,7 @@ module Actions
20
18
  end
21
19
 
22
20
  def self.default_parts
23
- self.resource_classes_order.map { |klass| klass.new.name }
21
+ resource_classes_order.map { |klass| klass.new.name }
24
22
  end
25
23
 
26
24
  # Registers the resource class to the humanizer. Usually, this
@@ -29,25 +27,23 @@ module Actions
29
27
  # The `register_resource` can be run more times for the same class,
30
28
  # effectively moving the resource to the end of the humanized form.
31
29
  def self.register_resource(resource_class)
32
- self.resource_classes_order.delete_if { |klass| klass.name == resource_class.name }
33
- self.resource_classes_order << resource_class
30
+ resource_classes_order.delete_if { |klass| klass.name == resource_class.name }
31
+ resource_classes_order << resource_class
34
32
  end
35
33
 
36
34
  def input(*parts)
37
- if parts.empty?
38
- parts = self.class.default_parts
39
- end
35
+ parts = self.class.default_parts if parts.empty?
40
36
  included_parts(parts, @input).map do |part|
41
37
  [part, humanize_resource(part, @input)]
42
38
  end
43
39
  end
44
40
 
45
41
  def included_parts(parts, data)
46
- parts.select { |part| data.has_key?(part) }
42
+ parts.select { |part| data.key?(part) }
47
43
  end
48
44
 
49
45
  def humanize_resource(name, data)
50
- if resource = self.class.resource(name)
46
+ if (resource = self.class.resource(name))
51
47
  { text: "#{resource.humanized_name} '#{resource.humanized_value(data)}'",
52
48
  link: resource.link(data) }
53
49
  end
@@ -62,13 +58,12 @@ module Actions
62
58
  name
63
59
  end
64
60
 
65
- def link(data)
66
- end
61
+ def link(data); end
67
62
 
68
63
  def humanized_value(data)
69
64
  fetch_data(data, name, :name) ||
70
- fetch_data(data, name, :label) ||
71
- fetch_data(data, name, :id)
65
+ fetch_data(data, name, :label) ||
66
+ fetch_data(data, name, :id)
72
67
  end
73
68
 
74
69
  def self.inherited(klass)
@@ -79,10 +74,10 @@ module Actions
79
74
 
80
75
  def fetch_data(data, *subkeys)
81
76
  if subkeys.empty?
82
- return data
77
+ data
83
78
  else
84
79
  head, *tail = subkeys
85
- if data.is_a?(Hash) && data.has_key?(head)
80
+ if data.is_a?(Hash) && data.key?(head)
86
81
  return fetch_data(data[head], *tail)
87
82
  else
88
83
  return nil
@@ -101,7 +96,7 @@ module Actions
101
96
  end
102
97
 
103
98
  def link(data)
104
- if ackey_id = fetch_data(data, :activation_key, :id)
99
+ if (ackey_id = fetch_data(data, :activation_key, :id))
105
100
  "/activation_keys/#{ackey_id}/info"
106
101
  end
107
102
  end
@@ -156,7 +151,7 @@ module Actions
156
151
  end
157
152
 
158
153
  def link(data)
159
- if content_view_id = fetch_data(data, :content_view, :id)
154
+ if (content_view_id = fetch_data(data, :content_view, :id))
160
155
  "#/content_views/#{content_view_id}/versions"
161
156
  end
162
157
  end
@@ -172,7 +167,7 @@ module Actions
172
167
  end
173
168
 
174
169
  def link(data)
175
- if product_id = fetch_data(data, :product, :id)
170
+ if (product_id = fetch_data(data, :product, :id))
176
171
  "#/products/#{product_id}/info"
177
172
  end
178
173
  end
@@ -188,7 +183,7 @@ module Actions
188
183
  end
189
184
 
190
185
  def link(data)
191
- if system_uuid = fetch_data(data, :system, :uuid)
186
+ if (system_uuid = fetch_data(data, :system, :uuid))
192
187
  "#/systems/#{system_uuid}/info"
193
188
  end
194
189
  end
@@ -204,7 +199,7 @@ module Actions
204
199
  end
205
200
 
206
201
  def link(data)
207
- if org_id = fetch_data(data, :organization, :id)
202
+ if (org_id = fetch_data(data, :organization, :id))
208
203
  "/organizations/#{org_id}/edit"
209
204
  end
210
205
  end
@@ -23,4 +23,3 @@ module Actions
23
23
  end
24
24
  end
25
25
  end
26
-
@@ -7,12 +7,12 @@ module Actions
7
7
  case proxy
8
8
  when :not_defined
9
9
  if klass.is_a?(String)
10
- raise ::Foreman::Exception.new(_('No proxy defined for execution'))
10
+ raise Foreman::Exception, _('No proxy defined for execution')
11
11
  else
12
12
  delegated_action = plan_action(klass, options)
13
13
  end
14
14
  when :not_available
15
- raise ::Foreman::Exception.new(_('All proxies with the required feature are unavailable at the moment'))
15
+ raise Foreman::Exception, _('All proxies with the required feature are unavailable at the moment')
16
16
  when ::SmartProxy
17
17
  delegated_action = plan_action(::Actions::ProxyAction, proxy, klass, options)
18
18
  end
@@ -1,18 +1,17 @@
1
1
  module Actions
2
2
  module Middleware
3
3
  class InheritTaskGroups < Dynflow::Middleware
4
-
5
4
  def delay(*args)
6
- pass *args
5
+ pass(*args)
7
6
  end
8
7
 
9
8
  def plan(*args)
10
9
  inherit_task_groups
11
- pass *args
10
+ pass(*args)
12
11
  end
13
12
 
14
13
  def run(*args)
15
- pass *args
14
+ pass(*args)
16
15
  collect_children_task_groups
17
16
  end
18
17
 
@@ -36,4 +35,3 @@ module Actions
36
35
  end
37
36
  end
38
37
  end
39
-
@@ -13,9 +13,7 @@
13
13
 
14
14
  module Actions
15
15
  module Middleware
16
-
17
16
  class KeepCurrentUser < Dynflow::Middleware
18
-
19
17
  def delay(*args)
20
18
  pass(*args).tap { store_current_user }
21
19
  end
@@ -54,7 +52,6 @@ module Actions
54
52
  ensure
55
53
  User.current = nil
56
54
  end
57
-
58
55
  end
59
56
  end
60
57
  end
@@ -1,7 +1,6 @@
1
1
  module Actions
2
2
  module Middleware
3
3
  class RecurringLogic < ::Dynflow::Middleware
4
-
5
4
  # ::Actions::Middleware::RecurringLogic
6
5
  #
7
6
  # A middleware designed to make action repeatable.
@@ -47,7 +47,7 @@ module Actions
47
47
  response = proxy.trigger_task(proxy_action_name,
48
48
  input.merge(:callback => { :task_id => task.id,
49
49
  :step_id => run_step_id }))
50
- output[:proxy_task_id] = response["task_id"]
50
+ output[:proxy_task_id] = response['task_id']
51
51
  end
52
52
  end
53
53
 
@@ -56,7 +56,7 @@ module Actions
56
56
  response = proxy.status_of_task(output[:proxy_task_id])
57
57
  if %w(stopped paused).include? response['state']
58
58
  if response['result'] == 'error'
59
- raise ::Foreman::Exception, _("The smart proxy task %s failed.") % (output[:proxy_task_id])
59
+ raise ::Foreman::Exception, _('The smart proxy task %s failed.') % output[:proxy_task_id]
60
60
  else
61
61
  on_data(response['actions'].find { |block_action| block_action['class'] == proxy_action_name }['output'])
62
62
  end
@@ -70,7 +70,7 @@ module Actions
70
70
 
71
71
  def cancel_proxy_task
72
72
  if output[:cancel_sent]
73
- error! ForemanTasks::Task::TaskCancelledException.new(_("Cancel enforced: the task might be still running on the proxy"))
73
+ error! ForemanTasks::Task::TaskCancelledException.new(_('Cancel enforced: the task might be still running on the proxy'))
74
74
  else
75
75
  proxy.cancel_task(output[:proxy_task_id])
76
76
  output[:cancel_sent] = true
@@ -112,7 +112,7 @@ module Actions
112
112
  def fill_continuous_output(continuous_output)
113
113
  failed_proxy_tasks.each do |failure_data|
114
114
  message = _('Initialization error: %s') %
115
- "#{failure_data[:exception_class]} - #{failure_data[:exception_message]}"
115
+ "#{failure_data[:exception_class]} - #{failure_data[:exception_message]}"
116
116
  continuous_output.add_output(message, 'debug', failure_data[:timestamp])
117
117
  end
118
118
  end
@@ -136,7 +136,7 @@ module Actions
136
136
  end
137
137
 
138
138
  def set_timeout!
139
- time = Time.now + input[:connection_options][:timeout]
139
+ time = Time.zone.now + input[:connection_options][:timeout]
140
140
  schedule_timeout(time)
141
141
  metadata[:timeout] = time.to_s
142
142
  end
@@ -145,8 +145,8 @@ module Actions
145
145
  # Fails if the plan is not finished within 60 seconds from the first task trigger attempt on the smart proxy
146
146
  # If the triggering fails, it retries 3 more times with 15 second delays
147
147
  { :retry_interval => Setting['foreman_tasks_proxy_action_retry_interval'] || 15,
148
- :retry_count => Setting['foreman_tasks_proxy_action_retry_count' ] || 4,
149
- :timeout => Setting['foreman_tasks_proxy_action_start_timeout'] || 60 }
148
+ :retry_count => Setting['foreman_tasks_proxy_action_retry_count'] || 4,
149
+ :timeout => Setting['foreman_tasks_proxy_action_start_timeout'] || 60 }
150
150
  end
151
151
 
152
152
  private
@@ -179,7 +179,7 @@ module Actions
179
179
  if failed_proxy_tasks.count < options[:retry_count]
180
180
  suspend do |suspended_action|
181
181
  @world.clock.ping suspended_action,
182
- Time.now + options[:retry_interval],
182
+ Time.zone.now + options[:retry_interval],
183
183
  event
184
184
  end
185
185
  else
@@ -1,6 +1,5 @@
1
1
  module Actions
2
2
  module Serializers
3
-
4
3
  class ActiveRecordSerializer < ::Dynflow::Serializers::Noop
5
4
  def serialize(arg)
6
5
  if arg.is_a? ActiveRecord::Base
@@ -20,7 +19,5 @@ module Actions
20
19
  end
21
20
  end
22
21
  end
23
-
24
22
  end
25
23
  end
26
-
@@ -1,7 +1,7 @@
1
1
  module ProxyAPI
2
2
  module ForemanDynflow
3
3
  class DynflowProxy
4
- PREFIX = 'dynflow'
4
+ PREFIX = 'dynflow'.freeze
5
5
 
6
6
  class Task < ProxyAPI::Resource
7
7
  def initialize(args)
@@ -24,11 +24,11 @@ module ProxyAPI
24
24
 
25
25
  # Cancel the command
26
26
  def cancel_task(proxy_task_id)
27
- MultiJson.load(Task.new(@args).send(:post, "", "#{ proxy_task_id }/cancel"))
27
+ MultiJson.load(Task.new(@args).send(:post, '', "#{proxy_task_id}/cancel"))
28
28
  end
29
29
 
30
30
  def status_of_task(proxy_task_id)
31
- MultiJson.load(Task.new(@args).send(:get, "#{ proxy_task_id }/status"))
31
+ MultiJson.load(Task.new(@args).send(:get, "#{proxy_task_id}/status"))
32
32
  end
33
33
 
34
34
  def tasks_count(state)
@@ -1,7 +1,6 @@
1
1
  module ForemanTasks
2
2
  module Concerns
3
3
  module ActionSubject
4
-
5
4
  extend ActiveSupport::Concern
6
5
 
7
6
  module ClassMethods
@@ -15,10 +14,10 @@ module ForemanTasks
15
14
  end
16
15
 
17
16
  def to_action_input
18
- raise 'The resource needs to be saved first' if self.new_record?
17
+ raise 'The resource needs to be saved first' if new_record?
19
18
 
20
19
  { id: id, name: name }.tap do |hash|
21
- hash.update(label: label) if self.respond_to? :label
20
+ hash.update(label: label) if respond_to? :label
22
21
  end
23
22
  end
24
23
 
@@ -36,13 +35,12 @@ module ForemanTasks
36
35
  def all_related_resources
37
36
  mine = Set.new Array(related_resources)
38
37
 
39
- get_all_related_resources = -> resource do
38
+ get_all_related_resources = lambda do |resource|
40
39
  resource.is_a?(ActionSubject) ? resource.all_related_resources : []
41
40
  end
42
41
 
43
- mine + mine.reduce(Set.new) { |s, resource| s + get_all_related_resources.(resource) }
42
+ mine + mine.reduce(Set.new) { |s, resource| s + get_all_related_resources.call(resource) }
44
43
  end
45
-
46
44
  end
47
45
  end
48
46
  end
@@ -1,29 +1,25 @@
1
1
  module ForemanTasks
2
2
  module Concerns
3
3
  module ActionTriggering
4
-
5
4
  extend ActiveSupport::Concern
6
5
 
7
6
  included do
8
- after_create :plan_create_action
9
- after_update :plan_update_action
10
- after_destroy :plan_destroy_action
7
+ after_create :plan_hook_action
8
+ after_update :plan_hook_action
9
+ after_destroy :plan_hook_action
11
10
 
12
11
  alias_method_chain :save, :dynflow_task_wrap
13
12
  end
14
13
 
14
+ # These three *_action methods are called before the save/destroy actually occurs
15
15
  # @override
16
- def create_action
17
- end
16
+ def create_action; end
18
17
 
19
18
  # @override
20
- def update_action
21
- end
19
+ def update_action; end
22
20
 
23
21
  # @override
24
- def destroy_action
25
- end
26
-
22
+ def destroy_action; end
27
23
 
28
24
  def save_with_dynflow_task_wrap(*args)
29
25
  dynflow_task_wrap(:save) { save_without_dynflow_task_wrap(*args) }
@@ -48,12 +44,12 @@ module ForemanTasks
48
44
  # this can be used when HostActionSubject is used for orchestration but you want to avoid
49
45
  # triggering more tasks by ActiveRecord callbacks within run/finalize phase of your task
50
46
  # e.g. host.disable_dynflow_hooks { |h| h.save }
51
- def disable_dynflow_hooks(&block)
47
+ def disable_dynflow_hooks
52
48
  @_disable_dynflow_hooks = true
53
49
 
54
50
  if block_given?
55
51
  begin
56
- block.call(self)
52
+ yield(self)
57
53
  ensure
58
54
  @_disable_dynflow_hooks = false
59
55
  end
@@ -75,19 +71,9 @@ module ForemanTasks
75
71
  @dynflow_sync_action = true
76
72
  end
77
73
 
78
- def plan_create_action
79
- plan_action(create_action, self) if create_action
80
- return true
81
- end
82
-
83
- def plan_update_action
84
- plan_action(update_action, self) if update_action
85
- return true
86
- end
87
-
88
- def plan_destroy_action
89
- plan_action(destroy_action, self) if destroy_action
90
- return true
74
+ def plan_hook_action
75
+ plan_action(@_dynflow_hook_action, self) if @_dynflow_hook_action
76
+ true
91
77
  end
92
78
 
93
79
  # Perform planning phase of the action tied with the model event.
@@ -115,26 +101,27 @@ module ForemanTasks
115
101
  # to unexpected results.
116
102
  def dynflow_task_wrap(method)
117
103
  if ForemanTasks.dynflow.config.disable_active_record_actions ||
118
- @_disable_dynflow_hooks ||
119
- @_dynflow_task_wrapped
104
+ @_disable_dynflow_hooks ||
105
+ @_dynflow_task_wrapped
120
106
  return yield
121
107
  end
122
108
  @_dynflow_task_wrapped = true
123
109
 
124
- action = case method
110
+ @_dynflow_hook_action = case method
125
111
  when :save
126
- self.new_record? ? create_action : update_action
112
+ new_record? ? create_action : update_action
127
113
  when :destroy
128
114
  destroy_action
129
115
  else
130
116
  raise 'unexpected method'
131
117
  end
132
- ensure_not_in_transaction! if action
118
+ ensure_not_in_transaction! if @_dynflow_hook_action
133
119
  yield.tap do |result|
134
120
  execute_planned_action if result
135
121
  sync_action_flag_reset!
136
122
  end
137
123
  ensure
124
+ @_dynflow_hook_action = nil
138
125
  @_dynflow_task_wrapped = false
139
126
  end
140
127
 
@@ -143,7 +130,7 @@ module ForemanTasks
143
130
  def ensure_not_in_transaction!
144
131
  # we don't care about transactions when using InThreadWorld
145
132
  if defined?(::Dynflow::Testing::InThreadWorld) &&
146
- ForemanTasks.dynflow.world.is_a?(::Dynflow::Testing::InThreadWorld)
133
+ ForemanTasks.dynflow.world.is_a?(::Dynflow::Testing::InThreadWorld)
147
134
  return
148
135
  end
149
136
  if self.class.connection.open_transactions > 0
@@ -159,7 +146,7 @@ module ForemanTasks
159
146
  run.wait
160
147
  if run.value.error?
161
148
  task = ForemanTasks::Task::DynflowTask.where(:external_id => @execution_plan.id).first!
162
- raise ForemanTasks::TaskError.new(task)
149
+ raise ForemanTasks::TaskError, task
163
150
  end
164
151
  end
165
152
  end