foreman-tasks 0.6.10 → 0.6.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|