rocketjob_mission_control 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -1
- data/app/controllers/rocket_job_mission_control/active_workers_controller.rb +1 -0
- data/app/controllers/rocket_job_mission_control/application_controller.rb +15 -2
- data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +19 -2
- data/app/controllers/rocket_job_mission_control/jobs_controller.rb +45 -17
- data/app/controllers/rocket_job_mission_control/servers_controller.rb +18 -2
- data/app/datatables/rocket_job_mission_control/abstract_datatable.rb +0 -1
- data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +8 -6
- data/app/datatables/rocket_job_mission_control/servers_datatable.rb +20 -8
- data/app/models/rocket_job_mission_control/access_policy.rb +50 -0
- data/app/models/rocket_job_mission_control/authorization.rb +22 -0
- data/app/views/rocket_job_mission_control/dirmon_entries/_sidebar.html.erb +5 -2
- data/app/views/rocket_job_mission_control/dirmon_entries/show.html.erb +8 -2
- data/app/views/rocket_job_mission_control/jobs/show.html.erb +9 -5
- data/app/views/rocket_job_mission_control/servers/index.html.erb +10 -8
- data/lib/rocket_job_mission_control/engine.rb +9 -0
- data/lib/rocket_job_mission_control/version.rb +1 -1
- data/test/controllers/rocket_job_mission_control/dirmon_entries_controller_test.rb +78 -1
- data/test/controllers/rocket_job_mission_control/jobs_controller_test.rb +52 -1
- data/test/controllers/rocket_job_mission_control/servers_controller_test.rb +58 -1
- data/test/test_helper.rb +12 -10
- data/vendor/assets/stylesheets/{fontawesome-all.min.css → fontawesome-all.min.css.erb} +1 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04c47815b195983663c44887317137d965b99c5a9e30d40f3b8969585dc7465a
|
4
|
+
data.tar.gz: 789ee3b6b5d9e006f8fa20d310fed0c30ed23dc89353a507cb7a544cfdaf46e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39413801aeb5be085f2f6ef7f7b9e44641efa786322126f34b9d05e5299ea149e92f5d6ef2d988521717d035d1a76bb300c5479ebf59a58441bb67212efd2621
|
7
|
+
data.tar.gz: 3f9e7b8308596809f4eeb73ed67da1f2fc0e65d879d7199f6f9d506acc2e33bfd7277a24cff3fb9b3a0706c940cfa7a0222acf4a22ecc13f8690c5ea3dea3672
|
data/Rakefile
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'bundler/setup'
|
4
4
|
|
5
|
-
|
5
|
+
require 'rails/version'
|
6
|
+
rakefile = Rails.version.to_f >= 5.2 ? '../rjmc/Rakefile' : '../rjmc4/Rakefile'
|
7
|
+
APP_RAKEFILE = File.expand_path(rakefile, __FILE__)
|
6
8
|
load 'rails/tasks/engine.rake'
|
7
9
|
|
8
10
|
require 'rake/testtask'
|
@@ -6,10 +6,23 @@ module RocketJobMissionControl
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def with_time_zone
|
9
|
+
def with_time_zone(&block)
|
10
10
|
if time_zone = session['time_zone'] || 'UTC'
|
11
|
-
Time.use_zone(time_zone)
|
11
|
+
Time.use_zone(time_zone, &block)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
def current_policy
|
16
|
+
@current_policy ||= begin
|
17
|
+
args =
|
18
|
+
if Config.authorization_callback
|
19
|
+
instance_exec(&Config.authorization_callback)
|
20
|
+
else
|
21
|
+
{roles: %i[admin]}
|
22
|
+
end
|
23
|
+
AccessPolicy.new(Authorization.new(args))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
14
27
|
end
|
15
28
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class DirmonEntriesController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_entry_or_redirect, except: [
|
4
|
+
before_filter :find_entry_or_redirect, except: %i[index disabled enabled failed pending new create]
|
5
|
+
before_filter :authorize_read, only: %i[index disabled enabled failed pending]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_entry_or_redirect, except: [
|
8
|
+
before_action :find_entry_or_redirect, except: %i[index disabled enabled failed pending new create]
|
9
|
+
before_action :authorize_read, only: %i[index disabled enabled failed pending]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
10
12
|
|
13
|
+
rescue_from AccessGranted::AccessDenied do |exception|
|
14
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
15
|
+
redirect_to :back, alert: 'Access not authorized.'
|
16
|
+
end
|
17
|
+
|
11
18
|
def index
|
12
19
|
@data_table_url = dirmon_entries_url(format: 'json')
|
13
20
|
render_datatable(RocketJob::DirmonEntry.all, 'All')
|
@@ -46,6 +53,7 @@ module RocketJobMissionControl
|
|
46
53
|
end
|
47
54
|
|
48
55
|
def create
|
56
|
+
authorize! :create, RocketJob::DirmonEntry
|
49
57
|
@dirmon_entry = RocketJob::DirmonEntry.new(dirmon_params)
|
50
58
|
if properties = params[:rocket_job_dirmon_entry][:properties]
|
51
59
|
@dirmon_entry.properties = JobSanitizer.sanitize(properties, @dirmon_entry.job_class, @dirmon_entry, false)
|
@@ -59,14 +67,17 @@ module RocketJobMissionControl
|
|
59
67
|
end
|
60
68
|
|
61
69
|
def destroy
|
70
|
+
authorize! :destroy, @dirmon_entry
|
62
71
|
@dirmon_entry.destroy
|
63
72
|
redirect_to(dirmon_entries_path)
|
64
73
|
end
|
65
74
|
|
66
75
|
def edit
|
76
|
+
authorize! :edit, @dirmon_entry
|
67
77
|
end
|
68
78
|
|
69
79
|
def update
|
80
|
+
authorize! :update, @dirmon_entry
|
70
81
|
if properties = params[:rocket_job_dirmon_entry][:properties]
|
71
82
|
@dirmon_entry.properties = JobSanitizer.sanitize(properties, @dirmon_entry.job_class, @dirmon_entry, false)
|
72
83
|
end
|
@@ -78,6 +89,7 @@ module RocketJobMissionControl
|
|
78
89
|
end
|
79
90
|
|
80
91
|
def enable
|
92
|
+
authorize! :enable, @dirmon_entry
|
81
93
|
if @dirmon_entry.may_enable?
|
82
94
|
@dirmon_entry.enable!
|
83
95
|
redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
|
@@ -88,6 +100,7 @@ module RocketJobMissionControl
|
|
88
100
|
end
|
89
101
|
|
90
102
|
def disable
|
103
|
+
authorize! :disable, @dirmon_entry
|
91
104
|
if @dirmon_entry.may_disable?
|
92
105
|
@dirmon_entry.disable!
|
93
106
|
redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
|
@@ -104,6 +117,10 @@ module RocketJobMissionControl
|
|
104
117
|
|
105
118
|
private
|
106
119
|
|
120
|
+
def authorize_read
|
121
|
+
authorize! :read, RocketJob::DirmonEntry
|
122
|
+
end
|
123
|
+
|
107
124
|
def show_sidebar
|
108
125
|
@dirmon_sidebar = true
|
109
126
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class JobsController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_job_or_redirect, except: [
|
4
|
+
before_filter :find_job_or_redirect, except: %i[index aborted completed failed paused queued running scheduled]
|
5
|
+
before_filter :authorize_read, only: %i[index running paused completed aborted failed queued scheduled]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_job_or_redirect, except: [
|
8
|
+
before_action :find_job_or_redirect, except: %i[index aborted completed failed paused queued running scheduled]
|
9
|
+
before_action :authorize_read, only: %i[index running paused completed aborted failed queued scheduled]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
12
|
+
|
10
13
|
rescue_from StandardError, with: :error_occurred
|
11
14
|
|
12
15
|
def index
|
@@ -17,10 +20,14 @@ module RocketJobMissionControl
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def running
|
20
|
-
jobs
|
23
|
+
# Prevent throttled jobs from displaying.
|
24
|
+
jobs = RocketJob::Job.
|
25
|
+
running.
|
26
|
+
where(:started_at.lte => (Time.now - 0.1)).
|
27
|
+
only(JobsDatatable::RUNNING_FIELDS)
|
21
28
|
@data_table_url = running_jobs_url(format: 'json')
|
22
29
|
|
23
|
-
render_datatable(jobs, 'Running', JobsDatatable::RUNNING_COLUMNS,
|
30
|
+
render_datatable(jobs, 'Running', JobsDatatable::RUNNING_COLUMNS, priority: :asc, created_at: :asc)
|
24
31
|
end
|
25
32
|
|
26
33
|
def paused
|
@@ -55,7 +62,7 @@ module RocketJobMissionControl
|
|
55
62
|
jobs = RocketJob::Job.queued_now.only(JobsDatatable::QUEUED_FIELDS)
|
56
63
|
@data_table_url = queued_jobs_url(format: 'json')
|
57
64
|
|
58
|
-
render_datatable(jobs, 'Queued', JobsDatatable::QUEUED_COLUMNS,
|
65
|
+
render_datatable(jobs, 'Queued', JobsDatatable::QUEUED_COLUMNS, priority: :asc, created_at: :asc)
|
59
66
|
end
|
60
67
|
|
61
68
|
def scheduled
|
@@ -66,6 +73,7 @@ module RocketJobMissionControl
|
|
66
73
|
end
|
67
74
|
|
68
75
|
def update
|
76
|
+
authorize! :update, @job
|
69
77
|
permitted_params = JobSanitizer.sanitize(params[:job], @job.class, @job)
|
70
78
|
if @job.errors.empty? && @job.valid? && @job.update_attributes(permitted_params)
|
71
79
|
redirect_to job_path(@job)
|
@@ -75,64 +83,75 @@ module RocketJobMissionControl
|
|
75
83
|
end
|
76
84
|
|
77
85
|
def abort
|
86
|
+
authorize! :abort, @job
|
78
87
|
@job.abort!
|
79
88
|
redirect_to(job_path(@job))
|
80
89
|
end
|
81
90
|
|
82
91
|
def destroy
|
92
|
+
authorize! :destroy, @job
|
83
93
|
@job.destroy
|
84
94
|
redirect_to(jobs_path)
|
85
95
|
end
|
86
96
|
|
87
97
|
def retry
|
98
|
+
authorize! :retry, @job
|
88
99
|
@job.retry!
|
89
100
|
redirect_to(job_path(@job))
|
90
101
|
end
|
91
102
|
|
92
103
|
def pause
|
104
|
+
authorize! :pause, @job
|
93
105
|
@job.pause!
|
94
106
|
redirect_to(job_path(@job))
|
95
107
|
end
|
96
108
|
|
97
109
|
def resume
|
110
|
+
authorize! :resume, @job
|
98
111
|
@job.resume!
|
99
112
|
redirect_to(job_path(@job))
|
100
113
|
end
|
101
114
|
|
102
115
|
def run_now
|
116
|
+
authorize! :run_now, @job
|
103
117
|
@job.unset(:run_at) if @job.scheduled?
|
104
118
|
redirect_to(job_path(@job))
|
105
119
|
end
|
106
120
|
|
107
121
|
def fail
|
122
|
+
authorize! :fail, @job
|
108
123
|
@job.fail!
|
109
124
|
|
110
125
|
redirect_to(job_path(@job))
|
111
126
|
end
|
112
127
|
|
113
128
|
def show
|
129
|
+
authorize! :read, @job
|
114
130
|
end
|
115
131
|
|
116
132
|
def edit
|
133
|
+
authorize! :edit, @job
|
117
134
|
end
|
118
135
|
|
119
136
|
def exceptions
|
137
|
+
authorize! :read, @job
|
120
138
|
@exceptions = @job.input.group_exceptions
|
121
139
|
end
|
122
140
|
|
123
141
|
def exception
|
142
|
+
authorize! :read, @job
|
124
143
|
error_type = params[:error_type]
|
125
144
|
offset = params.fetch(:offset, 0).to_i
|
126
145
|
|
127
146
|
unless error_type.present?
|
128
|
-
flash[:notice] = t(:no_errors, scope: [
|
147
|
+
flash[:notice] = t(:no_errors, scope: %i[job failures])
|
129
148
|
redirect_to(job_path(@job))
|
130
149
|
end
|
131
150
|
|
132
151
|
scope = @job.input.failed.where('exception.class_name' => error_type)
|
133
152
|
count = scope.count
|
134
153
|
unless count > 0
|
135
|
-
flash[:notice] = t(:no_errors, scope: [
|
154
|
+
flash[:notice] = t(:no_errors, scope: %i[job failures])
|
136
155
|
redirect_to(job_path(@job))
|
137
156
|
end
|
138
157
|
|
@@ -141,19 +160,23 @@ module RocketJobMissionControl
|
|
141
160
|
|
142
161
|
@pagination = {
|
143
162
|
offset: offset,
|
144
|
-
total: (count - 1)
|
163
|
+
total: (count - 1)
|
145
164
|
}
|
146
165
|
end
|
147
166
|
|
148
167
|
private
|
149
168
|
|
169
|
+
def authorize_read
|
170
|
+
authorize! :read, RocketJob::Job
|
171
|
+
end
|
172
|
+
|
150
173
|
def show_sidebar
|
151
174
|
@jobs_sidebar = true
|
152
175
|
end
|
153
176
|
|
154
177
|
def find_job_or_redirect
|
155
178
|
unless @job = RocketJob::Job.where(id: params[:id]).first
|
156
|
-
flash[:alert] = t(:failure, scope: [
|
179
|
+
flash[:alert] = t(:failure, scope: %i[job find], id: params[:id])
|
157
180
|
|
158
181
|
redirect_to(jobs_path)
|
159
182
|
end
|
@@ -169,8 +192,14 @@ module RocketJobMissionControl
|
|
169
192
|
else
|
170
193
|
logger.error "Error loading a job. #{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
|
171
194
|
end
|
172
|
-
|
173
|
-
|
195
|
+
|
196
|
+
flash[:danger] = if exception.is_a?(AccessGranted::AccessDenied)
|
197
|
+
'Access not authorized.'
|
198
|
+
else
|
199
|
+
'Error loading jobs.'
|
200
|
+
end
|
201
|
+
|
202
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
174
203
|
redirect_to :back
|
175
204
|
end
|
176
205
|
|
@@ -184,7 +213,7 @@ module RocketJobMissionControl
|
|
184
213
|
end
|
185
214
|
format.json do
|
186
215
|
query = RocketJobMissionControl::Query.new(jobs, sort_order)
|
187
|
-
query.search_columns = [
|
216
|
+
query.search_columns = %i[_type description]
|
188
217
|
query.display_columns = columns.collect { |c| c[:field] }.compact
|
189
218
|
render(json: JobsDatatable.new(view_context, query, columns))
|
190
219
|
end
|
@@ -194,13 +223,12 @@ module RocketJobMissionControl
|
|
194
223
|
def build_table_layout(columns)
|
195
224
|
index = 0
|
196
225
|
columns.collect do |column|
|
197
|
-
h = {data: index.to_s}
|
198
|
-
h[:width] = column[:width] if column.
|
199
|
-
h[:orderable] = column[:orderable] if column.
|
200
|
-
index
|
226
|
+
h = { data: index.to_s }
|
227
|
+
h[:width] = column[:width] if column.key?(:width)
|
228
|
+
h[:orderable] = column[:orderable] if column.key?(:orderable)
|
229
|
+
index += 1
|
201
230
|
h
|
202
231
|
end
|
203
232
|
end
|
204
|
-
|
205
233
|
end
|
206
234
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class ServersController < RocketJobMissionControl::ApplicationController
|
3
3
|
if Rails.version.to_i < 5
|
4
|
-
before_filter :find_server_or_redirect, only: [
|
4
|
+
before_filter :find_server_or_redirect, only: %i[stop pause resume destroy]
|
5
|
+
before_filter :authorize_read, only: %i[index starting running paused stopping zombie]
|
5
6
|
before_filter :show_sidebar
|
6
7
|
else
|
7
|
-
before_action :find_server_or_redirect, only: [
|
8
|
+
before_action :find_server_or_redirect, only: %i[stop pause resume destroy]
|
9
|
+
before_action :authorize_read, only: %i[index starting running paused stopping zombie]
|
8
10
|
before_action :show_sidebar
|
9
11
|
end
|
10
12
|
|
13
|
+
rescue_from AccessGranted::AccessDenied do |exception|
|
14
|
+
raise exception if Rails.env.development? || Rails.env.test?
|
15
|
+
redirect_to :back, alert: 'Access not authorized.'
|
16
|
+
end
|
17
|
+
|
11
18
|
def index
|
12
19
|
@data_table_url = servers_url(format: 'json')
|
13
20
|
@actions = [:pause_all, :resume_all, :stop_all, :destroy_zombies]
|
@@ -47,6 +54,7 @@ module RocketJobMissionControl
|
|
47
54
|
VALID_ACTIONS = [:stop_all, :pause_all, :resume_all, :destroy_zombies]
|
48
55
|
|
49
56
|
def update_all
|
57
|
+
authorize! :destroy, RocketJob::Server
|
50
58
|
server_action = params[:server_action].to_sym
|
51
59
|
if VALID_ACTIONS.include?(server_action)
|
52
60
|
RocketJob::Server.public_send(server_action.to_sym)
|
@@ -61,6 +69,7 @@ module RocketJobMissionControl
|
|
61
69
|
end
|
62
70
|
|
63
71
|
def stop
|
72
|
+
authorize! :stop, @server
|
64
73
|
if @server.may_stop?
|
65
74
|
@server.stop!
|
66
75
|
else
|
@@ -73,6 +82,7 @@ module RocketJobMissionControl
|
|
73
82
|
end
|
74
83
|
|
75
84
|
def destroy
|
85
|
+
authorize! :destroy, @server
|
76
86
|
@server.destroy
|
77
87
|
flash[:notice] = t(:success, scope: [:server, :destroy])
|
78
88
|
|
@@ -82,6 +92,7 @@ module RocketJobMissionControl
|
|
82
92
|
end
|
83
93
|
|
84
94
|
def pause
|
95
|
+
authorize! :pause, @server
|
85
96
|
if @server.may_pause?
|
86
97
|
@server.pause!
|
87
98
|
else
|
@@ -94,6 +105,7 @@ module RocketJobMissionControl
|
|
94
105
|
end
|
95
106
|
|
96
107
|
def resume
|
108
|
+
authorize! :resume, @server
|
97
109
|
if @server.may_resume?
|
98
110
|
@server.resume!
|
99
111
|
else
|
@@ -107,6 +119,10 @@ module RocketJobMissionControl
|
|
107
119
|
|
108
120
|
private
|
109
121
|
|
122
|
+
def authorize_read
|
123
|
+
authorize! :read, RocketJob::Server
|
124
|
+
end
|
125
|
+
|
110
126
|
def render_datatable(servers, description)
|
111
127
|
respond_to do |format|
|
112
128
|
format.html do
|
@@ -4,7 +4,7 @@ module RocketJobMissionControl
|
|
4
4
|
:abort_job_path, :job_path, :fail_job_path, :run_now_job_path, :pause_job_path,
|
5
5
|
:resume_job_path, :retry_job_path, :exception_job_path, :job_action_link, :exceptions_job_path, to: :@view
|
6
6
|
|
7
|
-
COMMON_FIELDS = [:id, :_type, :description, :completed_at, :created_at, :started_at, :state, :worker_name].freeze
|
7
|
+
COMMON_FIELDS = [:id, :_type, :description, :completed_at, :created_at, :started_at, :state, :worker_name, :login].freeze
|
8
8
|
|
9
9
|
ABORTED_COLUMNS = [
|
10
10
|
{display: 'Class', value: :class_with_link, field: '_type', width: '30%'},
|
@@ -156,19 +156,21 @@ module RocketJobMissionControl
|
|
156
156
|
def action_buttons(job)
|
157
157
|
events = valid_events(job)
|
158
158
|
buttons = "<div class='inline-job-actions'>"
|
159
|
-
if job.scheduled?
|
159
|
+
if job.scheduled? && view.can?(:run_now, job)
|
160
160
|
buttons += "#{ job_action_link('Run', run_now_job_path(job), :patch) }"
|
161
161
|
end
|
162
|
-
if events.include?(:pause)
|
162
|
+
if events.include?(:pause) && view.can?(:pause, job)
|
163
163
|
buttons += "#{ job_action_link('Pause', pause_job_path(job), :patch) }"
|
164
164
|
end
|
165
|
-
if events.include?(:resume)
|
165
|
+
if events.include?(:resume) && view.can?(:resume, job)
|
166
166
|
buttons += "#{ job_action_link('Resume', resume_job_path(job), :patch) }"
|
167
167
|
end
|
168
|
-
if events.include?(:retry)
|
168
|
+
if events.include?(:retry) && view.can?(:retry, job)
|
169
169
|
buttons += "#{ job_action_link('Retry', retry_job_path(job), :patch) }"
|
170
170
|
end
|
171
|
-
|
171
|
+
if view.can?(:destroy, job)
|
172
|
+
buttons += "#{ job_action_link('Destroy', job_path(job), :delete) }"
|
173
|
+
end
|
172
174
|
buttons += "</div>"
|
173
175
|
end
|
174
176
|
|