foreman-tasks 0.6.10 → 0.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +29 -12
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +13 -4
- data/app/controllers/foreman_tasks/tasks_controller.rb +28 -9
- data/app/models/foreman_tasks/concerns/action_triggering.rb +5 -1
- data/app/models/foreman_tasks/task.rb +26 -8
- data/app/views/foreman_tasks/tasks/_details.html.erb +33 -29
- data/deploy/foreman-tasks.service +1 -1
- data/lib/foreman_tasks.rb +1 -0
- data/lib/foreman_tasks/authorizer_ext.rb +19 -0
- data/lib/foreman_tasks/dynflow.rb +5 -8
- data/lib/foreman_tasks/dynflow/configuration.rb +5 -0
- data/lib/foreman_tasks/dynflow/console_authorizer.rb +52 -0
- data/lib/foreman_tasks/engine.rb +25 -4
- data/lib/foreman_tasks/tasks/test.rake +22 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +23 -0
- data/test/factories/task_factory.rb +41 -0
- data/test/foreman_tasks_test_helper.rb +8 -0
- data/test/helpers/foreman_tasks/tasks_helper_test.rb +48 -0
- data/test/support/dummy_dynflow_action.rb +4 -0
- data/test/unit/dynflow_console_authorizer_test.rb +79 -0
- data/test/unit/task_test.rb +37 -0
- metadata +47 -66
- data/test/tasks_test.rb +0 -7
- data/test/test_helper.rb +0 -15
data/README.md
CHANGED
@@ -1,25 +1,42 @@
|
|
1
1
|
Foreman Tasks
|
2
2
|
=============
|
3
3
|
|
4
|
-
Tasks management engine for Foreman. Gives you
|
5
|
-
happening/happened in your Foreman instance.
|
4
|
+
Tasks management engine for Foreman. Gives you an overview of what's
|
5
|
+
happening/happened in your Foreman instance. A framework for asynchronous tasks in Foreman.
|
6
|
+
|
7
|
+
* Website: [TheForeman.org](http://theforeman.org)
|
8
|
+
* ServerFault tag: [Foreman](http://serverfault.com/questions/tagged/foreman)
|
9
|
+
* Issues: [foreman-tasks Redmine](http://projects.theforeman.org/projects/foreman-tasks)
|
10
|
+
* Wiki: [Foreman wiki](http://projects.theforeman.org/projects/foreman/wiki/About)
|
11
|
+
* Community and support: #theforeman for general support, #theforeman-dev for development chat in [Freenode](irc.freenode.net)
|
12
|
+
* Mailing lists:
|
13
|
+
* [foreman-users](https://groups.google.com/forum/?fromgroups#!forum/foreman-users)
|
14
|
+
* [foreman-dev](https://groups.google.com/forum/?fromgroups#!forum/foreman-dev)
|
6
15
|
|
7
16
|
Installation
|
8
17
|
------------
|
9
18
|
|
10
|
-
|
19
|
+
Please see the Foreman manual for appropriate instructions:
|
11
20
|
|
12
|
-
|
13
|
-
gem 'dynflow', :git => 'https://github.com/Dynflow/dynflow.git'
|
14
|
-
gem 'foreman-tasks', :git => 'https://github.com/theforeman/foreman-tasks.git'
|
15
|
-
```
|
21
|
+
* [Foreman: How to Install a Plugin](http://theforeman.org/manuals/latest/index.html#6.1InstallaPlugin)
|
16
22
|
|
17
|
-
|
23
|
+
### Red Hat, CentOS, Fedora, Scientific Linux (rpm)
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
Set up the repo as explained in the link above, then run
|
26
|
+
|
27
|
+
# yum install ruby193-rubygem-foreman-tasks
|
28
|
+
|
29
|
+
### Bundle (gem)
|
30
|
+
|
31
|
+
Add the following to bundler.d/Gemfile.local.rb in your Foreman installation directory (/usr/share/foreman by default)
|
32
|
+
|
33
|
+
$ gem 'foreman-tasks'
|
34
|
+
|
35
|
+
Then run `bundle install` and `foreman-rake db:migrate` from the same directory
|
36
|
+
|
37
|
+
--------------
|
38
|
+
|
39
|
+
To verify that the installation was successful, go to Foreman, top bar **Administer > About** and check 'foreman-tasks' shows up in the **System Status** menu under the Plugins tab. You should also see a **'Tasks'** button under the **Monitor** menu in the top bar.
|
23
40
|
|
24
41
|
Usage
|
25
42
|
-----
|
@@ -26,7 +26,7 @@ module ForemanTasks
|
|
26
26
|
class BadRequest < Apipie::ParamError
|
27
27
|
end
|
28
28
|
|
29
|
-
before_filter :
|
29
|
+
before_filter :find_resource, :only => [:show]
|
30
30
|
|
31
31
|
api :GET, "/tasks/:id", "Show task details"
|
32
32
|
param :id, :identifier, desc: "UUID of the task"
|
@@ -79,7 +79,7 @@ module ForemanTasks
|
|
79
79
|
private
|
80
80
|
|
81
81
|
def search_tasks(search_params)
|
82
|
-
scope =
|
82
|
+
scope = resource_scope_for_index.select('DISTINCT foreman_tasks_tasks.*')
|
83
83
|
scope = ordering_scope(scope, search_params)
|
84
84
|
scope = search_scope(scope, search_params)
|
85
85
|
scope = active_scope(scope, search_params)
|
@@ -157,8 +157,17 @@ module ForemanTasks
|
|
157
157
|
|
158
158
|
private
|
159
159
|
|
160
|
-
def
|
161
|
-
@
|
160
|
+
def resource_scope(options = {})
|
161
|
+
@resource_scope ||= ForemanTasks::Task.authorized("#{action_permission}_foreman_tasks")
|
162
|
+
end
|
163
|
+
|
164
|
+
def action_permission
|
165
|
+
case params[:action]
|
166
|
+
when 'bulk_search'
|
167
|
+
:view
|
168
|
+
else
|
169
|
+
super
|
170
|
+
end
|
162
171
|
end
|
163
172
|
end
|
164
173
|
end
|
@@ -3,29 +3,29 @@ module ForemanTasks
|
|
3
3
|
include Foreman::Controller::AutoCompleteSearch
|
4
4
|
|
5
5
|
def show
|
6
|
-
@task =
|
6
|
+
@task = find_resource
|
7
7
|
end
|
8
8
|
|
9
9
|
def index
|
10
10
|
params[:order] ||= 'started_at DESC'
|
11
|
-
@tasks = filter(
|
11
|
+
@tasks = filter(resource_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def sub_tasks
|
15
|
-
task =
|
15
|
+
task = find_resource
|
16
16
|
@tasks = filter(task.sub_tasks)
|
17
17
|
render :index
|
18
18
|
end
|
19
19
|
|
20
20
|
def cancel_step
|
21
|
-
task =
|
21
|
+
task = find_dynflow_task
|
22
22
|
flash[:notice] = _("Trying to cancel step %s") % params[:step_id]
|
23
23
|
ForemanTasks.dynflow.world.event(task.external_id, params[:step_id].to_i, ::Dynflow::Action::Cancellable::Cancel).wait
|
24
24
|
redirect_to foreman_tasks_task_path(task)
|
25
25
|
end
|
26
26
|
|
27
27
|
def resume
|
28
|
-
task =
|
28
|
+
task = find_dynflow_task
|
29
29
|
if task.resumable?
|
30
30
|
ForemanTasks.dynflow.world.execute(task.execution_plan.id)
|
31
31
|
flash[:notice] = _('The execution was resumed.')
|
@@ -36,7 +36,7 @@ module ForemanTasks
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def unlock
|
39
|
-
task =
|
39
|
+
task = find_dynflow_task
|
40
40
|
if task.paused?
|
41
41
|
task.state = :stopped
|
42
42
|
task.save!
|
@@ -48,7 +48,7 @@ module ForemanTasks
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def force_unlock
|
51
|
-
task =
|
51
|
+
task = find_dynflow_task
|
52
52
|
task.state = :stopped
|
53
53
|
task.save!
|
54
54
|
flash[:notice] = _('The task resources were unlocked with force.')
|
@@ -62,8 +62,27 @@ module ForemanTasks
|
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
|
-
def
|
66
|
-
|
65
|
+
def controller_permission
|
66
|
+
'foreman_tasks'
|
67
|
+
end
|
68
|
+
|
69
|
+
def action_permission
|
70
|
+
case params[:action]
|
71
|
+
when 'sub_tasks'
|
72
|
+
:view
|
73
|
+
when 'resume', 'unlock', 'force_unlock', 'cancel_step'
|
74
|
+
:edit
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def resource_scope(options = {})
|
81
|
+
@resource_scope ||= ForemanTasks::Task.authorized("#{action_permission}_foreman_tasks")
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_dynflow_task
|
85
|
+
resource_scope.where(:type => 'ForemanTasks::Task::DynflowTask').find(params[:id])
|
67
86
|
end
|
68
87
|
|
69
88
|
def filter(scope)
|
@@ -73,6 +73,7 @@ module ForemanTasks
|
|
73
73
|
# of planning phase is expected to be commited when execution occurs. Also
|
74
74
|
# we want to be able to rollback the whole db operation when planning fails.
|
75
75
|
def plan_action(action_class, *args)
|
76
|
+
return if ForemanTasks.dynflow.config.disable_active_record_actions
|
76
77
|
@execution_plan = ::ForemanTasks.dynflow.world.plan(action_class, *args)
|
77
78
|
raise @execution_plan.errors.first if @execution_plan.error?
|
78
79
|
end
|
@@ -91,7 +92,10 @@ module ForemanTasks
|
|
91
92
|
# we would start the execution phase inside this transaction which would lead
|
92
93
|
# to unexpected results.
|
93
94
|
def dynflow_task_wrap(method)
|
94
|
-
|
95
|
+
if ForemanTasks.dynflow.config.disable_active_record_actions ||
|
96
|
+
@_dynflow_task_wrapped
|
97
|
+
return yield
|
98
|
+
end
|
95
99
|
@_dynflow_task_wrapped = true
|
96
100
|
|
97
101
|
action = case method
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'securerandom'
|
2
2
|
|
3
3
|
module ForemanTasks
|
4
4
|
class Task < ActiveRecord::Base
|
5
|
+
include Authorizable
|
5
6
|
|
6
7
|
# TODO missing validation of states
|
7
8
|
|
@@ -14,7 +15,8 @@ module ForemanTasks
|
|
14
15
|
|
15
16
|
# in fact, the task has only one owner but Rails don't let you to
|
16
17
|
# specify has_one relation though has_many relation
|
17
|
-
has_many :owners, :through => :locks, :source => :resource, :source_type => 'User'
|
18
|
+
has_many :owners, :through => :locks, :source => :resource, :source_type => 'User',
|
19
|
+
:conditions => ["foreman_tasks_locks.name = ?", Lock::OWNER_LOCK_NAME]
|
18
20
|
|
19
21
|
scoped_search :on => :id, :complete_value => false
|
20
22
|
scoped_search :on => :label, :complete_value => true
|
@@ -23,6 +25,7 @@ module ForemanTasks
|
|
23
25
|
scoped_search :on => :started_at, :complete_value => false
|
24
26
|
scoped_search :in => :locks, :on => :resource_type, :complete_value => true, :rename => "resource_type", :ext_method => :search_by_generic_resource
|
25
27
|
scoped_search :in => :locks, :on => :resource_id, :complete_value => false, :rename => "resource_id", :ext_method => :search_by_generic_resource
|
28
|
+
scoped_search :in => :owners, :on => :id, :complete_value => true, :rename => "owner.id", :ext_method => :search_by_owner
|
26
29
|
scoped_search :in => :owners, :on => :login, :complete_value => true, :rename => "owner.login", :ext_method => :search_by_owner
|
27
30
|
scoped_search :in => :owners, :on => :firstname, :complete_value => true, :rename => "owner.firstname", :ext_method => :search_by_owner
|
28
31
|
|
@@ -83,18 +86,28 @@ module ForemanTasks
|
|
83
86
|
end
|
84
87
|
|
85
88
|
def self.search_by_owner(key, operator, value)
|
89
|
+
return { :conditions => '0 = 1' } if value == 'current_user' && User.current.nil?
|
90
|
+
|
86
91
|
key_name = self.connection.quote_column_name(key.sub(/^.*\./,''))
|
87
|
-
joins = <<-
|
92
|
+
joins = <<-SQL
|
88
93
|
INNER JOIN foreman_tasks_locks AS foreman_tasks_locks_owner
|
89
94
|
ON (foreman_tasks_locks_owner.task_id = foreman_tasks_tasks.id AND
|
90
95
|
foreman_tasks_locks_owner.resource_type = 'User' AND
|
91
96
|
foreman_tasks_locks_owner.name = '#{Lock::OWNER_LOCK_NAME}')
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
97
|
+
SQL
|
98
|
+
if key !~ /\.id\Z/
|
99
|
+
joins << <<-SQL
|
100
|
+
INNER JOIN users
|
101
|
+
ON (users.id = foreman_tasks_locks_owner.resource_id)
|
102
|
+
SQL
|
103
|
+
end
|
96
104
|
condition = if key.blank?
|
97
105
|
sanitize_sql_for_conditions(["users.login #{operator} ? or users.firstname #{operator} ? ", value, value])
|
106
|
+
elsif key =~ /\.id\Z/
|
107
|
+
if value == 'current_user'
|
108
|
+
value = User.current.id
|
109
|
+
end
|
110
|
+
sanitize_sql_for_conditions(["foreman_tasks_locks_owner.resource_id #{operator} ?", value])
|
98
111
|
else
|
99
112
|
sanitize_sql_for_conditions(["users.#{key_name} #{operator} ?", value])
|
100
113
|
end
|
@@ -112,10 +125,15 @@ module ForemanTasks
|
|
112
125
|
end
|
113
126
|
end
|
114
127
|
|
128
|
+
def self.authorized_resource_name
|
129
|
+
# We don't want STI subclasses to have separate permissions
|
130
|
+
'ForemanTasks::Task'
|
131
|
+
end
|
132
|
+
|
115
133
|
protected
|
116
134
|
|
117
135
|
def generate_id
|
118
|
-
self.id ||=
|
136
|
+
self.id ||= SecureRandom.uuid
|
119
137
|
end
|
120
138
|
end
|
121
139
|
end
|
@@ -1,26 +1,27 @@
|
|
1
1
|
<p>
|
2
2
|
<%= link_to(_('Auto Reload'), '', class: %w(btn btn-sm btn-default reload-button hidden)) %>
|
3
|
+
<% if authorized_for(:permission => :edit_foreman_tasks, :auth_object => @task) %>
|
4
|
+
<%= link_to(_('Dynflow console'),
|
5
|
+
format((defined?(Rails) ? request.script_name : '') + '/foreman_tasks/dynflow/%s', @task.external_id),
|
6
|
+
class: %w(btn btn-sm btn-default)) if Setting['dynflow_enable_console'] %>
|
3
7
|
|
4
|
-
|
5
|
-
|
6
|
-
|
8
|
+
<%= link_to(_('Resume'),
|
9
|
+
resume_foreman_tasks_task_path(@task),
|
10
|
+
class: ['btn', 'btn-sm', 'btn-primary', ('disabled' unless @task.resumable?)].compact,
|
11
|
+
method: :post) %>
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
<%= link_to(_('Unlock'),
|
14
|
+
'',
|
15
|
+
class: ['btn', 'btn-sm', 'btn-warning', 'reload-button-stop', ('disabled' unless @task.state == 'paused')].compact,
|
16
|
+
:'data-toggle' => "modal",
|
17
|
+
:'data-target' => "#unlock_modal") %>
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<%= link_to(_('Force Unlock'),
|
20
|
-
'',
|
21
|
-
class: ['btn', 'btn-sm', 'btn-danger', 'reload-button-stop', ('disabled' if @task.state == 'stopped')].compact,
|
22
|
-
:'data-toggle' => "modal",
|
23
|
-
:'data-target' => "#force_unlock_modal") %>
|
19
|
+
<%= link_to(_('Force Unlock'),
|
20
|
+
'',
|
21
|
+
class: ['btn', 'btn-sm', 'btn-danger', 'reload-button-stop', ('disabled' if @task.state == 'stopped')].compact,
|
22
|
+
:'data-toggle' => "modal",
|
23
|
+
:'data-target' => "#force_unlock_modal") %>
|
24
|
+
<% end %>
|
24
25
|
</p>
|
25
26
|
|
26
27
|
<div class="modal fade" id="unlock_modal" tabindex="-1" role="dialog" aria-labelledby="Deploy" aria-hidden="true">
|
@@ -95,7 +96,7 @@
|
|
95
96
|
</div>
|
96
97
|
<div>
|
97
98
|
<span class="param-name"><%= _("Result") %>:</span>
|
98
|
-
<span class="param-value"><%= @task.result %></span>
|
99
|
+
<span class="param-value"><%= @task.state == 'running' ? '-' : @task.result %></span>
|
99
100
|
</div>
|
100
101
|
<div>
|
101
102
|
<span class="param-name"><%= _("Params") %>:</span>
|
@@ -115,16 +116,19 @@
|
|
115
116
|
<div class="col-xs-11">
|
116
117
|
<div class="progress progress-striped <%= 'active' if @task.state == 'running' %>">
|
117
118
|
<% progress = 100 * @task.progress %>
|
118
|
-
<%
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
<% progress_class = if @task.state == 'running'
|
120
|
+
nil
|
121
|
+
else
|
122
|
+
case @task.result
|
123
|
+
when 'success'
|
124
|
+
'progress-bar-success'
|
125
|
+
when 'error'
|
126
|
+
'progress-bar-danger'
|
127
|
+
else
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end %>
|
131
|
+
<% classes = ['progress-bar', progress_class] %>
|
128
132
|
<div class="<%= classes.join ' ' %>"
|
129
133
|
role="progressbar"
|
130
134
|
aria-valuenow="<%= progress %>"
|
data/lib/foreman_tasks.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
module ForemanTasks
|
2
|
+
# Monkey path until http://projects.theforeman.org/issues/8919 is
|
3
|
+
# resolved and released
|
4
|
+
module AuthorizerExt
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
alias_method_chain :resource_name, :authorized_resource_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def resource_name_with_authorized_resource_name(klass)
|
12
|
+
if klass.respond_to?(:authorized_resource_name)
|
13
|
+
return klass.authorized_resource_name
|
14
|
+
else
|
15
|
+
resource_name_without_authorized_resource_name(klass)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require 'dynflow'
|
2
3
|
|
3
4
|
module ForemanTasks
|
@@ -6,6 +7,7 @@ module ForemanTasks
|
|
6
7
|
require 'foreman_tasks/dynflow/configuration'
|
7
8
|
require 'foreman_tasks/dynflow/persistence'
|
8
9
|
require 'foreman_tasks/dynflow/daemon'
|
10
|
+
require 'foreman_tasks/dynflow/console_authorizer'
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
@required = false
|
@@ -82,14 +84,9 @@ module ForemanTasks
|
|
82
84
|
def web_console
|
83
85
|
::Dynflow::WebConsole.setup do
|
84
86
|
before do
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
if Setting[:dynflow_console_require_auth] &&
|
89
|
-
(!Setting[:dynflow_enable_console] ||
|
90
|
-
(user_id.nil? || !User.find(user_id).admin) ||
|
91
|
-
Time.now.to_i > expires_at)
|
92
|
-
redirect('dashboard')
|
87
|
+
if !Setting[:dynflow_enable_console] ||
|
88
|
+
(Setting[:dynflow_console_require_auth] && !ConsoleAuthorizer.new(env).allow?)
|
89
|
+
halt 403, 'Access forbidden'
|
93
90
|
end
|
94
91
|
end
|
95
92
|
|
@@ -33,6 +33,11 @@ module ForemanTasks
|
|
33
33
|
# what rake tasks should run their own executor, not depending on the external one
|
34
34
|
attr_accessor :rake_tasks_with_executor
|
35
35
|
|
36
|
+
# if true, the ForemanTasks::Concerns::ActionTriggering will make
|
37
|
+
# no effect. Useful for testing, where we mignt not want to execute
|
38
|
+
# the orchestration tied to the models.
|
39
|
+
attr_accessor :disable_active_record_actions
|
40
|
+
|
36
41
|
def initialize
|
37
42
|
self.action_logger = Rails.logger
|
38
43
|
self.dynflow_logger = Rails.logger
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module ForemanTasks
|
3
|
+
class Dynflow::ConsoleAuthorizer
|
4
|
+
def initialize(env)
|
5
|
+
@rack_request = Rack::Request.new(env)
|
6
|
+
@user_id, @expires_at = @rack_request.session.values_at('user', 'expires_at')
|
7
|
+
@user = User.find_by_id(@user_id) unless session_expired?
|
8
|
+
end
|
9
|
+
|
10
|
+
def allow?
|
11
|
+
@user && (unlimited_edit? || authorized_for_task?)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def session_expired?
|
17
|
+
Time.now.to_i > @expires_at.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def unlimited_edit?
|
21
|
+
return true if @user.admin?
|
22
|
+
# users with unlimited edit_foreman_tasks can operate with the
|
23
|
+
# console no matter what task it is…
|
24
|
+
edit_permission = Permission.where(:name => :edit_foreman_tasks, :resource_type => ForemanTasks::Task.name).first
|
25
|
+
if @user.filters.joins(:filterings).unlimited.where('filterings.permission_id' => edit_permission).first
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorized_for_task?
|
31
|
+
if task = extract_task
|
32
|
+
begin
|
33
|
+
original_user = User.current
|
34
|
+
User.current = @user
|
35
|
+
return Authorizer.new(@user).can?(:edit_foreman_tasks, task)
|
36
|
+
ensure
|
37
|
+
User.current = original_user
|
38
|
+
end
|
39
|
+
else
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_task
|
45
|
+
dynflow_id = @rack_request.path_info[/^\/([\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})/,1]
|
46
|
+
unless dynflow_id.empty?
|
47
|
+
ForemanTasks::Task::DynflowTask.where(:external_id => dynflow_id).first
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -14,6 +14,22 @@ module ForemanTasks
|
|
14
14
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
15
15
|
:caption => N_('Tasks'),
|
16
16
|
:parent => :monitor_menu
|
17
|
+
|
18
|
+
security_block :foreman_tasks do |map|
|
19
|
+
permission :view_foreman_tasks, {:'foreman_tasks/tasks' => [:auto_complete_search, :sub_tasks, :index, :show],
|
20
|
+
:'foreman_tasks/api/tasks' => [:bulk_search, :show] }, :resource_type => ForemanTasks::Task.name
|
21
|
+
permission :edit_foreman_tasks, {:'foreman_tasks/tasks' => [:resume, :unlock, :force_unlock, :cancel_step]}, :resource_type => ForemanTasks::Task.name
|
22
|
+
end
|
23
|
+
|
24
|
+
view_permission = Permission.where(:name => :view_foreman_tasks, :resource_type => ForemanTasks::Task.name).first
|
25
|
+
unless Role.anonymous.permissions.include?(view_permission)
|
26
|
+
Role.anonymous.filters.create(:search => 'owner.id = current_user') do |filter|
|
27
|
+
filter.filterings.build { |f| f.permission = view_permission }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
role "Tasks Manager", [:view_foreman_tasks, :edit_foreman_tasks]
|
32
|
+
role "Tasks Reader", [:view_foreman_tasks]
|
17
33
|
end
|
18
34
|
end
|
19
35
|
|
@@ -53,11 +69,8 @@ module ForemanTasks
|
|
53
69
|
end
|
54
70
|
|
55
71
|
initializer "foreman_tasks.initialize_dynflow" do
|
56
|
-
ForemanTasks.dynflow.eager_load_actions!
|
57
|
-
ActionDispatch::Reloader.to_prepare do
|
58
|
-
ForemanTasks.dynflow.eager_load_actions!
|
59
|
-
end
|
60
72
|
|
73
|
+
ForemanTasks.dynflow.eager_load_actions!
|
61
74
|
ForemanTasks.dynflow.config.increase_db_pool_size
|
62
75
|
|
63
76
|
unless ForemanTasks.dynflow.config.lazy_initialization
|
@@ -73,8 +86,16 @@ module ForemanTasks
|
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
89
|
+
config.to_prepare do
|
90
|
+
ForemanTasks.dynflow.eager_load_actions!
|
91
|
+
|
92
|
+
Authorizer.send(:include, AuthorizerExt)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
76
96
|
rake_tasks do
|
77
97
|
load File.expand_path('../tasks/dynflow.rake', __FILE__)
|
98
|
+
load File.expand_path('../tasks/test.rake', __FILE__)
|
78
99
|
end
|
79
100
|
end
|
80
101
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
namespace :test do
|
2
|
+
task :foreman_tasks => 'db:test:prepare' do
|
3
|
+
test_task = Rake::TestTask.new('foreman_tasks_test_task') do |t|
|
4
|
+
t.libs << ["test", "#{ForemanTasks::Engine.root}/test"]
|
5
|
+
t.test_files = ["#{ForemanTasks::Engine.root}/test/**/*_test.rb"]
|
6
|
+
t.verbose = true
|
7
|
+
end
|
8
|
+
|
9
|
+
Rake::Task[test_task.name].invoke
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::Task[:test].enhance do
|
14
|
+
Rake::Task['test:foreman_tasks'].invoke
|
15
|
+
end
|
16
|
+
|
17
|
+
load 'tasks/jenkins.rake'
|
18
|
+
if Rake::Task.task_defined?(:'jenkins:unit')
|
19
|
+
Rake::Task["jenkins:unit"].enhance do
|
20
|
+
Rake::Task['test:foreman_tasks'].invoke
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "foreman_tasks_test_helper"
|
2
|
+
|
3
|
+
module ForemanTasks
|
4
|
+
class Api::TasksControllerTest < ActionController::TestCase
|
5
|
+
describe 'tasks api controller' do
|
6
|
+
tests ForemanTasks::Api::TasksController
|
7
|
+
|
8
|
+
before do
|
9
|
+
User.current = User.where(:login => 'apiadmin').first
|
10
|
+
@request.env['HTTP_ACCEPT'] = 'application/json'
|
11
|
+
@request.env['CONTENT_TYPE'] = 'application/json'
|
12
|
+
@task = FactoryGirl.create(:dynflow_task, :user_create_task)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'searches for task on GET' do
|
16
|
+
get(:show, :id => @task.id)
|
17
|
+
assert_response :success
|
18
|
+
assert_template 'api/tasks/show'
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :some_task, :class => ForemanTasks::Task do
|
3
|
+
sequence(:label) { |n| "task#{n}" }
|
4
|
+
type 'ForemanTasks::Task'
|
5
|
+
state 'stopped'
|
6
|
+
result 'success'
|
7
|
+
|
8
|
+
transient do
|
9
|
+
set_owner nil
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:create) do |task, evaluator|
|
13
|
+
ForemanTasks::Lock.owner!(evaluator.set_owner, task.id) if evaluator.set_owner
|
14
|
+
end
|
15
|
+
|
16
|
+
factory :dynflow_task, :class => ForemanTasks::Task::DynflowTask do
|
17
|
+
label "Support::DummyDynflowAction"
|
18
|
+
type "ForemanTasks::Task::DynflowTask"
|
19
|
+
started_at "2014-10-01 11:15:55"
|
20
|
+
ended_at "2014-10-01 11:15:57"
|
21
|
+
state "stopped"
|
22
|
+
result "success"
|
23
|
+
parent_task_id nil
|
24
|
+
|
25
|
+
after(:build) do |task|
|
26
|
+
dynflow_task = ForemanTasks.dynflow.world.plan(Support::DummyDynflowAction)
|
27
|
+
# remove the task created automatically by the persistence
|
28
|
+
ForemanTasks::Task.where(:external_id => dynflow_task.id).delete_all
|
29
|
+
task.external_id = dynflow_task.id
|
30
|
+
end
|
31
|
+
|
32
|
+
trait :user_create_task do
|
33
|
+
label "Actions::User::Create"
|
34
|
+
end
|
35
|
+
|
36
|
+
trait :product_create_task do
|
37
|
+
label "Actions::Katello::Product::Create"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative './support/dummy_dynflow_action'
|
3
|
+
|
4
|
+
FactoryGirl.definition_file_paths = ["#{ForemanTasks::Engine.root}/test/factories"]
|
5
|
+
FactoryGirl.find_definitions
|
6
|
+
|
7
|
+
ForemanTasks.dynflow.require!
|
8
|
+
ForemanTasks.dynflow.config.disable_active_record_actions = true
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "foreman_tasks_test_helper"
|
2
|
+
|
3
|
+
module ForemanTasks
|
4
|
+
class TasksHelperTest < ActionView::TestCase
|
5
|
+
|
6
|
+
describe 'when formatting simple input' do
|
7
|
+
before do
|
8
|
+
@task = FactoryGirl.build(:dynflow_task, :user_create_task)
|
9
|
+
humanized = {:action=>"Create", :input=>[[:user, {:text=>"user 'Anonymous Admin'", :link=>nil}]], :output=>"", :errors=>[]}
|
10
|
+
@task.stubs(:input).returns({"user"=>{"id"=>1, "name"=>"Anonymous Admin"}, "locale"=>"en"})
|
11
|
+
@task.stubs(:humanized).returns(humanized)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'formats the task input properly' do
|
15
|
+
expects(:h).with("user 'Anonymous Admin'")
|
16
|
+
format_task_input(@task)
|
17
|
+
expects(:h).with("Create user 'Anonymous Admin'")
|
18
|
+
format_task_input(@task, true)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'when formatting input' do
|
24
|
+
before do
|
25
|
+
@task = FactoryGirl.build(:dynflow_task, :product_create_task)
|
26
|
+
humanized = {:action=>"Create",
|
27
|
+
:input=>[[:product, {:text=>"product 'product-2'", :link=>"#/products/3/info"}], [:organization, {:text=>"organization 'test-0'", :link=>"/organizations/3/edit"}]],
|
28
|
+
:output=>"",
|
29
|
+
:errors=>[]}
|
30
|
+
input = {"product"=>{"id"=>3, "name"=>"product-2", "label"=>"product-2", "cp_id"=>nil},
|
31
|
+
"provider"=>{"id"=>3, "name"=>"Anonymous"},
|
32
|
+
"organization"=>{"id"=>3, "name"=>"test-0", "label"=>"test-0"},
|
33
|
+
"cp_id"=>"1412251033866",
|
34
|
+
"locale"=>"en"}
|
35
|
+
@task.stubs(:input).returns(input)
|
36
|
+
@task.stubs(:humanized).returns(humanized)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'formats the task input properly' do
|
40
|
+
response = "product 'product-2'; organization 'test-0'"
|
41
|
+
expects(:h).with(response)
|
42
|
+
format_task_input(@task)
|
43
|
+
expects(:h).with("Create #{response}")
|
44
|
+
format_task_input(@task, true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "foreman_tasks_test_helper"
|
2
|
+
|
3
|
+
module ForemanTasks
|
4
|
+
class DynflowConsoleAuthorizerTest < ActiveSupport::TestCase
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
before do
|
8
|
+
User.current = User.where(:login => 'apiadmin').first
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:own_task) { FactoryGirl.create(:dynflow_task, :set_owner => user) }
|
12
|
+
let(:foreign_task) { FactoryGirl.create(:dynflow_task) }
|
13
|
+
|
14
|
+
let(:edit_foreman_tasks_permission) do
|
15
|
+
FactoryGirl.build(:permission).tap do |permission|
|
16
|
+
permission.name = :edit_foreman_tasks
|
17
|
+
permission.resource_type = ForemanTasks::Task.name
|
18
|
+
permission.save!
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def dynflow_console_authorized?(task = nil)
|
23
|
+
dynflow_path = '/'
|
24
|
+
dynflow_path += task.external_id.to_s if task
|
25
|
+
dynflow_rack_env = { "rack.session" => { "user" => user.id, "expires_at" => Time.now + 100 },
|
26
|
+
"PATH_INFO" => dynflow_path}
|
27
|
+
ForemanTasks::Dynflow::ConsoleAuthorizer.new(dynflow_rack_env).allow?
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'admin user' do
|
31
|
+
let(:user) { FactoryGirl.create(:user, :admin) }
|
32
|
+
it 'can see all tasks' do
|
33
|
+
assert dynflow_console_authorized?
|
34
|
+
assert dynflow_console_authorized?(own_task)
|
35
|
+
assert dynflow_console_authorized?(foreign_task)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'user with unlimited edit_foreman_tasks permissions' do
|
40
|
+
let(:user) do
|
41
|
+
user_role = FactoryGirl.create(:user_user_role)
|
42
|
+
FactoryGirl.create(:filter,
|
43
|
+
:role => user_role.role, :permissions => [edit_foreman_tasks_permission])
|
44
|
+
user_role.owner
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can see all tasks' do
|
48
|
+
assert dynflow_console_authorized?
|
49
|
+
assert dynflow_console_authorized?(own_task)
|
50
|
+
assert dynflow_console_authorized?(foreign_task)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'user with limited edit_foreman_tasks permissions' do
|
55
|
+
let(:user) do
|
56
|
+
user_role = FactoryGirl.create(:user_user_role)
|
57
|
+
FactoryGirl.create(:filter,
|
58
|
+
:search => 'owner.id = current_user',
|
59
|
+
:role => user_role.role, :permissions => [edit_foreman_tasks_permission])
|
60
|
+
user_role.owner
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can see only the tasks he has permissions on' do
|
64
|
+
refute dynflow_console_authorized?
|
65
|
+
assert dynflow_console_authorized?(own_task)
|
66
|
+
refute dynflow_console_authorized?(foreign_task)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'user without edit_foreman_tasks permissions' do
|
71
|
+
let(:user) { FactoryGirl.create(:user) }
|
72
|
+
it 'can not see any tasks' do
|
73
|
+
refute dynflow_console_authorized?
|
74
|
+
refute dynflow_console_authorized?(own_task)
|
75
|
+
refute dynflow_console_authorized?(foreign_task)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'foreman_tasks_test_helper'
|
2
|
+
|
3
|
+
class TasksTest < ActiveSupport::TestCase
|
4
|
+
describe 'filtering by current user' do
|
5
|
+
before { @original_current_user = User.current }
|
6
|
+
after { User.current = @original_current_user }
|
7
|
+
|
8
|
+
test "can search the tasks by current_user" do
|
9
|
+
user_one = FactoryGirl.create(:user)
|
10
|
+
user_two = FactoryGirl.create(:user)
|
11
|
+
|
12
|
+
task_one = FactoryGirl.create(:some_task, :set_owner => user_one)
|
13
|
+
task_two = FactoryGirl.create(:some_task, :set_owner => user_two)
|
14
|
+
|
15
|
+
User.current = user_one
|
16
|
+
assert_equal [task_one], ForemanTasks::Task.search_for("owner.id = current_user")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'authorization filtering' do
|
21
|
+
it 'can filter by the task subject' do
|
22
|
+
user_role = FactoryGirl.create(:user_user_role)
|
23
|
+
user = user_role.owner
|
24
|
+
role = user_role.role
|
25
|
+
permission = FactoryGirl.build(:permission)
|
26
|
+
permission.resource_type = 'ForemanTasks::Task'
|
27
|
+
permission.save!
|
28
|
+
FactoryGirl.create(:filter, :role => role, :permissions => [permission])
|
29
|
+
|
30
|
+
User.current = user
|
31
|
+
task = FactoryGirl.create(:dynflow_task)
|
32
|
+
|
33
|
+
auth = Authorizer.new(user)
|
34
|
+
assert auth.can?(permission.name.to_sym, task)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,40 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: rails
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 3.2.0
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 3.2.0
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: uuidtools
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '0'
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
46
14
|
- !ruby/object:Gem::Dependency
|
47
15
|
name: dynflow
|
48
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,65 +94,73 @@ executables: []
|
|
126
94
|
extensions: []
|
127
95
|
extra_rdoc_files: []
|
128
96
|
files:
|
129
|
-
- app/assets/stylesheets/foreman_tasks/application.css.scss
|
130
97
|
- app/helpers/foreman_tasks/tasks_helper.rb
|
98
|
+
- app/models/foreman_tasks/task/dynflow_task.rb
|
99
|
+
- app/models/foreman_tasks/concerns/host_action_subject.rb
|
100
|
+
- app/models/foreman_tasks/concerns/action_triggering.rb
|
101
|
+
- app/models/foreman_tasks/concerns/architecture_action_subject.rb
|
102
|
+
- app/models/foreman_tasks/concerns/action_subject.rb
|
103
|
+
- app/models/foreman_tasks/lock.rb
|
104
|
+
- app/models/foreman_tasks/task.rb
|
105
|
+
- app/models/setting/foreman_tasks.rb
|
106
|
+
- app/assets/stylesheets/foreman_tasks/application.css.scss
|
107
|
+
- app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb
|
108
|
+
- app/controllers/foreman_tasks/api/tasks_controller.rb
|
109
|
+
- app/controllers/foreman_tasks/tasks_controller.rb
|
131
110
|
- app/lib/actions/helpers/args_serialization.rb
|
132
|
-
- app/lib/actions/helpers/humanizer.rb
|
133
111
|
- app/lib/actions/helpers/lock.rb
|
134
|
-
- app/lib/actions/
|
135
|
-
- app/lib/actions/base.rb
|
112
|
+
- app/lib/actions/helpers/humanizer.rb
|
136
113
|
- app/lib/actions/bulk_action.rb
|
137
|
-
- app/lib/actions/middleware/keep_current_user.rb
|
138
|
-
- app/lib/actions/foreman/host/import_facts.rb
|
139
114
|
- app/lib/actions/foreman/architecture/create.rb
|
140
115
|
- app/lib/actions/foreman/architecture/update.rb
|
141
116
|
- app/lib/actions/foreman/architecture/destroy.rb
|
142
|
-
- app/
|
143
|
-
- app/
|
144
|
-
- app/
|
117
|
+
- app/lib/actions/foreman/host/import_facts.rb
|
118
|
+
- app/lib/actions/entry_action.rb
|
119
|
+
- app/lib/actions/base.rb
|
120
|
+
- app/lib/actions/middleware/keep_current_user.rb
|
145
121
|
- app/views/foreman_tasks/tasks/_details.html.erb
|
146
122
|
- app/views/foreman_tasks/tasks/index.html.erb
|
147
|
-
- app/views/foreman_tasks/tasks/
|
123
|
+
- app/views/foreman_tasks/tasks/_running_steps.html.erb
|
148
124
|
- app/views/foreman_tasks/tasks/_errors.html.erb
|
125
|
+
- app/views/foreman_tasks/tasks/_raw.html.erb
|
126
|
+
- app/views/foreman_tasks/tasks/show.html.erb
|
149
127
|
- app/views/foreman_tasks/tasks/_locks.html.erb
|
150
|
-
- app/
|
151
|
-
- app/controllers/foreman_tasks/tasks_controller.rb
|
152
|
-
- app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb
|
153
|
-
- app/models/foreman_tasks/concerns/architecture_action_subject.rb
|
154
|
-
- app/models/foreman_tasks/concerns/action_triggering.rb
|
155
|
-
- app/models/foreman_tasks/concerns/host_action_subject.rb
|
156
|
-
- app/models/foreman_tasks/concerns/action_subject.rb
|
157
|
-
- app/models/foreman_tasks/task/dynflow_task.rb
|
158
|
-
- app/models/foreman_tasks/lock.rb
|
159
|
-
- app/models/foreman_tasks/task.rb
|
160
|
-
- app/models/setting/foreman_tasks.rb
|
128
|
+
- app/views/foreman_tasks/api/tasks/show.json.rabl
|
161
129
|
- bin/dynflow-executor
|
162
130
|
- bin/foreman-tasks
|
163
131
|
- config/routes.rb
|
164
|
-
- db/migrate/20131209122644_create_foreman_tasks_locks.rb
|
165
132
|
- db/migrate/20131205204140_create_foreman_tasks.rb
|
166
133
|
- db/migrate/20140324104010_remove_foreman_tasks_progress.rb
|
167
134
|
- db/migrate/20140813215942_add_parent_task_id.rb
|
168
|
-
-
|
135
|
+
- db/migrate/20131209122644_create_foreman_tasks_locks.rb
|
169
136
|
- deploy/foreman-tasks.service
|
170
137
|
- deploy/foreman-tasks.sysconfig
|
138
|
+
- deploy/foreman-tasks.init
|
171
139
|
- lib/tasks/gettext.rake
|
140
|
+
- lib/foreman-tasks.rb
|
172
141
|
- lib/foreman_tasks/tasks/dynflow.rake
|
173
|
-
- lib/foreman_tasks/
|
142
|
+
- lib/foreman_tasks/tasks/test.rake
|
174
143
|
- lib/foreman_tasks/version.rb
|
175
144
|
- lib/foreman_tasks/triggers.rb
|
176
|
-
- lib/foreman_tasks/
|
145
|
+
- lib/foreman_tasks/dynflow.rb
|
146
|
+
- lib/foreman_tasks/dynflow/console_authorizer.rb
|
177
147
|
- lib/foreman_tasks/dynflow/configuration.rb
|
178
148
|
- lib/foreman_tasks/dynflow/persistence.rb
|
179
149
|
- lib/foreman_tasks/dynflow/daemon.rb
|
180
|
-
- lib/foreman_tasks/
|
150
|
+
- lib/foreman_tasks/authorizer_ext.rb
|
151
|
+
- lib/foreman_tasks/engine.rb
|
152
|
+
- lib/foreman_tasks/task_error.rb
|
181
153
|
- lib/foreman_tasks.rb
|
182
|
-
- lib/foreman-tasks.rb
|
183
154
|
- LICENSE
|
184
155
|
- README.md
|
185
|
-
- test/
|
186
|
-
- test/
|
187
|
-
|
156
|
+
- test/helpers/foreman_tasks/tasks_helper_test.rb
|
157
|
+
- test/support/dummy_dynflow_action.rb
|
158
|
+
- test/foreman_tasks_test_helper.rb
|
159
|
+
- test/controllers/api/tasks_controller_test.rb
|
160
|
+
- test/factories/task_factory.rb
|
161
|
+
- test/unit/dynflow_console_authorizer_test.rb
|
162
|
+
- test/unit/task_test.rb
|
163
|
+
homepage: https://github.com/theforeman/foreman-tasks
|
188
164
|
licenses: []
|
189
165
|
post_install_message:
|
190
166
|
rdoc_options: []
|
@@ -209,6 +185,11 @@ signing_key:
|
|
209
185
|
specification_version: 3
|
210
186
|
summary: Foreman plugin for showing tasks information for resoruces and users
|
211
187
|
test_files:
|
212
|
-
- test/
|
213
|
-
- test/
|
188
|
+
- test/helpers/foreman_tasks/tasks_helper_test.rb
|
189
|
+
- test/support/dummy_dynflow_action.rb
|
190
|
+
- test/foreman_tasks_test_helper.rb
|
191
|
+
- test/controllers/api/tasks_controller_test.rb
|
192
|
+
- test/factories/task_factory.rb
|
193
|
+
- test/unit/dynflow_console_authorizer_test.rb
|
194
|
+
- test/unit/task_test.rb
|
214
195
|
has_rdoc:
|
data/test/tasks_test.rb
DELETED
data/test/test_helper.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# Configure Rails Environment
|
2
|
-
ENV["RAILS_ENV"] = "test"
|
3
|
-
|
4
|
-
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
5
|
-
require "rails/test_help"
|
6
|
-
|
7
|
-
Rails.backtrace_cleaner.remove_silencers!
|
8
|
-
|
9
|
-
# Load support files
|
10
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
11
|
-
|
12
|
-
# Load fixtures from the engine
|
13
|
-
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
14
|
-
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
15
|
-
end
|