mobilize-base 1.29 → 1.33
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 +19 -10
- data/lib/mobilize-base/extensions/google_drive/file.rb +7 -7
- data/lib/mobilize-base/extensions/resque-server/views/queues.erb +59 -0
- data/lib/mobilize-base/extensions/resque-server/views/working.erb +85 -0
- data/lib/mobilize-base/extensions/string.rb +12 -4
- data/lib/mobilize-base/extensions/yaml.rb +10 -7
- data/lib/mobilize-base/handlers/gbook.rb +25 -38
- data/lib/mobilize-base/handlers/gdrive.rb +8 -0
- data/lib/mobilize-base/handlers/gfile.rb +4 -2
- data/lib/mobilize-base/handlers/gridfs.rb +19 -24
- data/lib/mobilize-base/handlers/gsheet.rb +13 -7
- data/lib/mobilize-base/handlers/resque.rb +9 -3
- data/lib/mobilize-base/helpers/job_helper.rb +54 -0
- data/lib/mobilize-base/helpers/jobtracker_helper.rb +147 -0
- data/lib/mobilize-base/helpers/runner_helper.rb +83 -0
- data/lib/mobilize-base/helpers/stage_helper.rb +38 -0
- data/lib/mobilize-base/jobtracker.rb +16 -192
- data/lib/mobilize-base/models/job.rb +36 -48
- data/lib/mobilize-base/models/runner.rb +22 -122
- data/lib/mobilize-base/models/stage.rb +14 -35
- data/lib/mobilize-base/tasks.rb +16 -3
- data/lib/mobilize-base/version.rb +1 -1
- data/lib/mobilize-base.rb +5 -1
- data/lib/samples/gdrive.yml +6 -0
- data/lib/samples/gridfs.yml +0 -3
- data/lib/samples/gsheet.yml +4 -4
- data/mobilize-base.gemspec +3 -3
- data/test/base_job_rows.yml +5 -1
- data/test/mobilize-base_test.rb +20 -61
- data/test/test_helper.rb +79 -0
- metadata +57 -25
- checksums.yaml +0 -7
@@ -0,0 +1,147 @@
|
|
1
|
+
module Mobilize
|
2
|
+
module Jobtracker
|
3
|
+
def Jobtracker.config
|
4
|
+
Base.config('jobtracker')
|
5
|
+
end
|
6
|
+
|
7
|
+
#modify this to increase the frequency of request cycles
|
8
|
+
def Jobtracker.cycle_freq
|
9
|
+
Jobtracker.config['cycle_freq']
|
10
|
+
end
|
11
|
+
|
12
|
+
#frequency of notifications
|
13
|
+
def Jobtracker.notification_freq
|
14
|
+
Jobtracker.config['notification_freq']
|
15
|
+
end
|
16
|
+
|
17
|
+
def Jobtracker.runner_read_freq
|
18
|
+
Jobtracker.config['runner_read_freq']
|
19
|
+
end
|
20
|
+
|
21
|
+
#long running tolerance
|
22
|
+
def Jobtracker.max_run_time
|
23
|
+
Jobtracker.config['max_run_time']
|
24
|
+
end
|
25
|
+
|
26
|
+
def Jobtracker.admins
|
27
|
+
Jobtracker.config['admins']
|
28
|
+
end
|
29
|
+
|
30
|
+
def Jobtracker.admin_emails
|
31
|
+
Jobtracker.admins.map{|a| a['email'] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def Jobtracker.worker
|
35
|
+
Resque.find_worker_by_path("jobtracker")
|
36
|
+
end
|
37
|
+
|
38
|
+
def Jobtracker.workers(state="all")
|
39
|
+
Resque.workers(state)
|
40
|
+
end
|
41
|
+
|
42
|
+
def Jobtracker.status
|
43
|
+
args = Jobtracker.get_args
|
44
|
+
return args['status'] if args
|
45
|
+
job = Resque.jobs.select{|j| j['args'].first=='jobtracker'}.first
|
46
|
+
return 'queued' if job
|
47
|
+
return 'stopped'
|
48
|
+
end
|
49
|
+
|
50
|
+
def Jobtracker.update_status(msg)
|
51
|
+
#this is to keep jobtracker from resisting stop commands
|
52
|
+
return false if Jobtracker.status=="stopping"
|
53
|
+
#Jobtracker has no persistent database state
|
54
|
+
Resque.set_worker_args_by_path("jobtracker",{'status'=>msg})
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
def Jobtracker.restart
|
59
|
+
Jobtracker.stop!
|
60
|
+
Jobtracker.start
|
61
|
+
end
|
62
|
+
|
63
|
+
def Jobtracker.set_args(args)
|
64
|
+
Resque.set_worker_args(Jobtracker.worker,args)
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
|
68
|
+
def Jobtracker.get_args
|
69
|
+
Resque.get_worker_args(Jobtracker.worker)
|
70
|
+
end
|
71
|
+
|
72
|
+
def Jobtracker.kill_workers
|
73
|
+
Resque.kill_workers
|
74
|
+
end
|
75
|
+
|
76
|
+
def Jobtracker.kill_idle_workers
|
77
|
+
Resque.kill_idle_workers
|
78
|
+
end
|
79
|
+
|
80
|
+
def Jobtracker.kill_idle_and_stale_workers
|
81
|
+
Resque.kill_idle_and_stale_workers
|
82
|
+
end
|
83
|
+
|
84
|
+
def Jobtracker.prep_workers
|
85
|
+
Resque.prep_workers
|
86
|
+
end
|
87
|
+
|
88
|
+
def Jobtracker.failures
|
89
|
+
Resque.failures
|
90
|
+
end
|
91
|
+
|
92
|
+
def Jobtracker.start
|
93
|
+
if Jobtracker.status!='stopped'
|
94
|
+
Jobtracker.update_status("Jobtracker still #{Jobtracker.status}")
|
95
|
+
else
|
96
|
+
#make sure that workers are running and at the right number
|
97
|
+
#Resque.prep_workers
|
98
|
+
#queue up the jobtracker (starts the perform method)
|
99
|
+
Jobtracker.enqueue!
|
100
|
+
end
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
|
104
|
+
def Jobtracker.enqueue!
|
105
|
+
::Resque::Job.create(Resque.queue_name, Jobtracker, 'jobtracker',{})
|
106
|
+
end
|
107
|
+
|
108
|
+
def Jobtracker.restart!
|
109
|
+
Jobtracker.stop!
|
110
|
+
Jobtracker.start
|
111
|
+
return true
|
112
|
+
end
|
113
|
+
|
114
|
+
def Jobtracker.restart_workers!
|
115
|
+
Jobtracker.kill_workers
|
116
|
+
sleep 10
|
117
|
+
Jobtracker.prep_workers
|
118
|
+
Jobtracker.update_status("put workers back on the queue")
|
119
|
+
end
|
120
|
+
|
121
|
+
def Jobtracker.stop!
|
122
|
+
#send signal for Jobtracker to check for
|
123
|
+
Jobtracker.update_status('stopping')
|
124
|
+
sleep 5
|
125
|
+
i=0
|
126
|
+
while Jobtracker.status=='stopping'
|
127
|
+
puts "#{Jobtracker.to_s} still on queue, waiting"
|
128
|
+
sleep 5
|
129
|
+
i+=1
|
130
|
+
end
|
131
|
+
return true
|
132
|
+
end
|
133
|
+
|
134
|
+
def Jobtracker.last_notification
|
135
|
+
return Jobtracker.get_args["last_notification"] if Jobtracker.get_args
|
136
|
+
end
|
137
|
+
|
138
|
+
def Jobtracker.last_notification=(time)
|
139
|
+
Jobtracker.set_args({"last_notification"=>time})
|
140
|
+
end
|
141
|
+
|
142
|
+
def Jobtracker.notif_due?
|
143
|
+
last_duetime = Time.now.utc - Jobtracker.notification_freq
|
144
|
+
return (Jobtracker.last_notification.to_s.length==0 || Jobtracker.last_notification.to_datetime < last_duetime)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#this module adds convenience methods to the Runner model
|
2
|
+
module Mobilize
|
3
|
+
module RunnerHelper
|
4
|
+
def headers
|
5
|
+
%w{name active trigger status stage1 stage2 stage3 stage4 stage5}
|
6
|
+
end
|
7
|
+
|
8
|
+
def title
|
9
|
+
r = self
|
10
|
+
r.path.split("/").first
|
11
|
+
end
|
12
|
+
|
13
|
+
def worker
|
14
|
+
r = self
|
15
|
+
Mobilize::Resque.find_worker_by_path(r.path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def dataset
|
19
|
+
r = self
|
20
|
+
Dataset.find_or_create_by_handler_and_path("gsheet",r.path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def gbook(gdrive_slot)
|
24
|
+
r = self
|
25
|
+
title = r.path.split("/").first
|
26
|
+
Gbook.find_by_path(title,gdrive_slot)
|
27
|
+
end
|
28
|
+
|
29
|
+
def gsheet(gdrive_slot)
|
30
|
+
r = self
|
31
|
+
u = r.user
|
32
|
+
jobs_sheet = Gsheet.find_by_path(r.path,gdrive_slot)
|
33
|
+
#make sure the user has a runner with a jobs sheet and has write privileges on the spreadsheet
|
34
|
+
unless (jobs_sheet and jobs_sheet.spreadsheet.acl_entry(u.email).ie{|e| e and e.role=="writer"})
|
35
|
+
#only give the user edit permissions if they're the ones
|
36
|
+
#creating it
|
37
|
+
jobs_sheet = Gsheet.find_or_create_by_path(r.path,gdrive_slot)
|
38
|
+
unless jobs_sheet.spreadsheet.acl_entry(u.email).ie{|e| e and e.role=="owner"}
|
39
|
+
jobs_sheet.spreadsheet.update_acl(u.email,"writer")
|
40
|
+
end
|
41
|
+
jobs_sheet.add_headers(r.headers)
|
42
|
+
begin;jobs_sheet.delete_sheet1;rescue;end #don't care if sheet1 deletion fails
|
43
|
+
end
|
44
|
+
return jobs_sheet
|
45
|
+
end
|
46
|
+
|
47
|
+
def jobs(jname=nil)
|
48
|
+
r = self
|
49
|
+
js = Job.where(:path=>/^#{r.path.escape_regex}/).to_a
|
50
|
+
if jname
|
51
|
+
return js.sel{|j| j.name == jname}.first
|
52
|
+
else
|
53
|
+
return js
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def user
|
58
|
+
r = self
|
59
|
+
user_name = r.path.split("_")[1..-1].join("_").split("(").first.split("/").first
|
60
|
+
User.where(:name=>user_name).first
|
61
|
+
end
|
62
|
+
|
63
|
+
def update_status(msg)
|
64
|
+
r = self
|
65
|
+
r.update_attributes(:status=>msg, :status_at=>Time.now.utc)
|
66
|
+
Mobilize::Resque.set_worker_args_by_path(r.path,{'status'=>msg})
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_working?
|
71
|
+
r = self
|
72
|
+
Mobilize::Resque.active_paths.include?(r.path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def is_due?
|
76
|
+
r = self.reload
|
77
|
+
return false if r.is_working?
|
78
|
+
prev_due_time = Time.now.utc - Jobtracker.runner_read_freq
|
79
|
+
return true if r.started_at.nil? or r.started_at < prev_due_time
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#this module adds convenience methods to the Stage model
|
2
|
+
module Mobilize
|
3
|
+
module StageHelper
|
4
|
+
def idx
|
5
|
+
s = self
|
6
|
+
s.path.split("/").last.gsub("stage","").to_i
|
7
|
+
end
|
8
|
+
|
9
|
+
def out_dst
|
10
|
+
#this gives a dataset that points to the output
|
11
|
+
#allowing you to determine its size
|
12
|
+
#before committing to a read or write
|
13
|
+
s = self
|
14
|
+
Dataset.find_by_url(s.response['out_url']) if s.response and s.response['out_url']
|
15
|
+
end
|
16
|
+
|
17
|
+
def err_dst
|
18
|
+
#this gives a dataset that points to the output
|
19
|
+
#allowing you to determine its size
|
20
|
+
#before committing to a read or write
|
21
|
+
s = self
|
22
|
+
Dataset.find_by_url(s.response['err_url']) if s.response and s.response['err_url']
|
23
|
+
end
|
24
|
+
|
25
|
+
def params
|
26
|
+
s = self
|
27
|
+
p = YAML.easy_load(s.param_string)
|
28
|
+
raise "Must resolve to Hash" unless p.class==Hash
|
29
|
+
return p
|
30
|
+
end
|
31
|
+
|
32
|
+
def job
|
33
|
+
s = self
|
34
|
+
job_path = s.path.split("/")[0..-2].join("/")
|
35
|
+
Job.where(:path=>job_path).first
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,152 +1,13 @@
|
|
1
1
|
module Mobilize
|
2
2
|
module Jobtracker
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
#modify this to increase the frequency of request cycles
|
8
|
-
def Jobtracker.cycle_freq
|
9
|
-
Jobtracker.config['cycle_freq']
|
10
|
-
end
|
11
|
-
|
12
|
-
#frequency of notifications
|
13
|
-
def Jobtracker.notification_freq
|
14
|
-
Jobtracker.config['notification_freq']
|
15
|
-
end
|
16
|
-
|
17
|
-
def Jobtracker.runner_read_freq
|
18
|
-
Jobtracker.config['runner_read_freq']
|
19
|
-
end
|
20
|
-
|
21
|
-
#long running tolerance
|
22
|
-
def Jobtracker.max_run_time
|
23
|
-
Jobtracker.config['max_run_time']
|
24
|
-
end
|
25
|
-
|
26
|
-
def Jobtracker.admins
|
27
|
-
Jobtracker.config['admins']
|
28
|
-
end
|
29
|
-
|
30
|
-
def Jobtracker.admin_emails
|
31
|
-
Jobtracker.admins.map{|a| a['email'] }
|
32
|
-
end
|
33
|
-
|
34
|
-
def Jobtracker.worker
|
35
|
-
Resque.find_worker_by_path("jobtracker")
|
36
|
-
end
|
37
|
-
|
38
|
-
def Jobtracker.workers(state="all")
|
39
|
-
Resque.workers(state)
|
40
|
-
end
|
41
|
-
|
42
|
-
def Jobtracker.status
|
43
|
-
args = Jobtracker.get_args
|
44
|
-
return args['status'] if args
|
45
|
-
job = Resque.jobs.select{|j| j['args'].first=='jobtracker'}.first
|
46
|
-
return 'queued' if job
|
47
|
-
return 'stopped'
|
48
|
-
end
|
49
|
-
|
50
|
-
def Jobtracker.update_status(msg)
|
51
|
-
#Jobtracker has no persistent database state
|
52
|
-
Resque.set_worker_args_by_path("jobtracker",{'status'=>msg})
|
53
|
-
return true
|
54
|
-
end
|
55
|
-
|
56
|
-
def Jobtracker.restart
|
57
|
-
Jobtracker.stop!
|
58
|
-
Jobtracker.start
|
59
|
-
end
|
60
|
-
|
61
|
-
def Jobtracker.set_args(args)
|
62
|
-
Resque.set_worker_args(Jobtracker.worker,args)
|
63
|
-
return true
|
64
|
-
end
|
65
|
-
|
66
|
-
def Jobtracker.get_args
|
67
|
-
Resque.get_worker_args(Jobtracker.worker)
|
68
|
-
end
|
69
|
-
|
70
|
-
def Jobtracker.kill_workers
|
71
|
-
Resque.kill_workers
|
72
|
-
end
|
73
|
-
|
74
|
-
def Jobtracker.kill_idle_workers
|
75
|
-
Resque.kill_idle_workers
|
76
|
-
end
|
77
|
-
|
78
|
-
def Jobtracker.kill_idle_and_stale_workers
|
79
|
-
Resque.kill_idle_and_stale_workers
|
80
|
-
end
|
81
|
-
|
82
|
-
def Jobtracker.prep_workers
|
83
|
-
Resque.prep_workers
|
84
|
-
end
|
85
|
-
|
86
|
-
def Jobtracker.failures
|
87
|
-
Resque.failures
|
88
|
-
end
|
89
|
-
|
90
|
-
def Jobtracker.start
|
91
|
-
if Jobtracker.status!='stopped'
|
92
|
-
Jobtracker.update_status("Jobtracker still #{Jobtracker.status}")
|
93
|
-
else
|
94
|
-
#make sure that workers are running and at the right number
|
95
|
-
#Resque.prep_workers
|
96
|
-
#queue up the jobtracker (starts the perform method)
|
97
|
-
Jobtracker.enqueue!
|
98
|
-
end
|
99
|
-
return true
|
100
|
-
end
|
101
|
-
|
102
|
-
def Jobtracker.enqueue!
|
103
|
-
::Resque::Job.create(Resque.queue_name, Jobtracker, 'jobtracker',{})
|
104
|
-
end
|
105
|
-
|
106
|
-
def Jobtracker.restart!
|
107
|
-
Jobtracker.stop!
|
108
|
-
Jobtracker.start
|
109
|
-
return true
|
110
|
-
end
|
111
|
-
|
112
|
-
def Jobtracker.restart_workers!
|
113
|
-
Jobtracker.kill_workers
|
114
|
-
sleep 10
|
115
|
-
Jobtracker.prep_workers
|
116
|
-
Jobtracker.update_status("put workers back on the queue")
|
117
|
-
end
|
118
|
-
|
119
|
-
def Jobtracker.stop!
|
120
|
-
#send signal for Jobtracker to check for
|
121
|
-
Jobtracker.update_status('stopping')
|
122
|
-
sleep 5
|
123
|
-
i=0
|
124
|
-
while Jobtracker.status=='stopping'
|
125
|
-
Jobtracker.update_status("#{Jobtracker.to_s} still on queue, waiting")
|
126
|
-
sleep 5
|
127
|
-
i+=1
|
128
|
-
end
|
129
|
-
return true
|
130
|
-
end
|
131
|
-
|
132
|
-
def Jobtracker.last_notification
|
133
|
-
return Jobtracker.get_args["last_notification"] if Jobtracker.get_args
|
134
|
-
end
|
135
|
-
|
136
|
-
def Jobtracker.last_notification=(time)
|
137
|
-
Jobtracker.set_args({"last_notification"=>time})
|
138
|
-
end
|
139
|
-
|
140
|
-
def Jobtracker.notif_due?
|
141
|
-
last_duetime = Time.now.utc - Jobtracker.notification_freq
|
142
|
-
return (Jobtracker.last_notification.to_s.length==0 || Jobtracker.last_notification.to_datetime < last_duetime)
|
143
|
-
end
|
3
|
+
#adds convenience methods
|
4
|
+
require "#{File.dirname(__FILE__)}/helpers/jobtracker_helper"
|
144
5
|
|
145
6
|
def Jobtracker.max_run_time_workers
|
146
7
|
#return workers who have been cranking away for 6+ hours
|
147
8
|
workers = Jobtracker.workers('working').select do |w|
|
148
|
-
w.job['
|
149
|
-
(Time.now.utc - Time.parse(w.job['
|
9
|
+
w.job['run_at'].to_s.length>0 and
|
10
|
+
(Time.now.utc - Time.parse(w.job['run_at'])) > Jobtracker.max_run_time
|
150
11
|
end
|
151
12
|
return workers
|
152
13
|
end
|
@@ -183,15 +44,25 @@ module Mobilize
|
|
183
44
|
end
|
184
45
|
lws = Jobtracker.max_run_time_workers
|
185
46
|
if lws.length>0
|
47
|
+
bod = begin
|
48
|
+
lws.map{|w| w.job['payload']['args']}.first.join("\n")
|
49
|
+
rescue
|
50
|
+
"Failed to get job names"
|
51
|
+
end
|
186
52
|
n = {}
|
187
53
|
n['subject'] = "#{lws.length.to_s} max run time jobs"
|
188
|
-
n['body'] =
|
54
|
+
n['body'] = bod
|
189
55
|
n['to'] = Jobtracker.admin_emails.join(",")
|
190
56
|
notifs << n
|
191
57
|
end
|
192
58
|
#deliver each email generated
|
193
59
|
notifs.each do |notif|
|
194
|
-
|
60
|
+
begin
|
61
|
+
Email.write(notif).deliver
|
62
|
+
rescue
|
63
|
+
#log email on failure
|
64
|
+
Jobtracker.update_status("Failed to deliver #{notif.to_s}")
|
65
|
+
end
|
195
66
|
end
|
196
67
|
#update notification time so JT knows to wait a while
|
197
68
|
Jobtracker.last_notification = Time.now.utc.to_s
|
@@ -243,52 +114,5 @@ module Mobilize
|
|
243
114
|
end.to_s.strip
|
244
115
|
Time.parse(deploy_time)
|
245
116
|
end
|
246
|
-
|
247
|
-
#test methods
|
248
|
-
def Jobtracker.restart_test_redis
|
249
|
-
Jobtracker.stop_test_redis
|
250
|
-
if !system("which redis-server")
|
251
|
-
raise "** can't find `redis-server` in your path, you need redis to run Resque and Mobilize"
|
252
|
-
end
|
253
|
-
"redis-server #{Base.root}/test/redis-test.conf".bash
|
254
|
-
end
|
255
|
-
|
256
|
-
def Jobtracker.stop_test_redis
|
257
|
-
processes = `ps -A -o pid,command | grep [r]edis-test`.split($/)
|
258
|
-
pids = processes.map { |process| process.split(" ")[0] }
|
259
|
-
puts "Killing test redis server..."
|
260
|
-
pids.each { |pid| Process.kill("TERM", pid.to_i) }
|
261
|
-
puts "removing redis db dump file"
|
262
|
-
sleep 5
|
263
|
-
`rm -f #{Base.root}/test/dump.rdb #{Base.root}/test/dump-cluster.rdb`
|
264
|
-
end
|
265
|
-
|
266
|
-
def Jobtracker.set_test_env
|
267
|
-
ENV['MOBILIZE_ENV']='test'
|
268
|
-
::Resque.redis="localhost:9736"
|
269
|
-
mongoid_config_path = "#{Base.root}/config/mobilize/mongoid.yml"
|
270
|
-
Mongoid.load!(mongoid_config_path, Base.env)
|
271
|
-
end
|
272
|
-
|
273
|
-
def Jobtracker.drop_test_db
|
274
|
-
Jobtracker.set_test_env
|
275
|
-
Mongoid.session(:default).collections.each do |collection|
|
276
|
-
unless collection.name =~ /^system\./
|
277
|
-
collection.drop
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
def Jobtracker.build_test_runner(user_name)
|
283
|
-
Jobtracker.set_test_env
|
284
|
-
u = User.where(:name=>user_name).first
|
285
|
-
Jobtracker.update_status("delete old books and datasets")
|
286
|
-
# delete any old runner from previous test runs
|
287
|
-
gdrive_slot = Gdrive.owner_email
|
288
|
-
u.runner.gsheet(gdrive_slot).spreadsheet.delete
|
289
|
-
Jobtracker.update_status("enqueue jobtracker, wait 45s")
|
290
|
-
Mobilize::Jobtracker.start
|
291
|
-
sleep 45
|
292
|
-
end
|
293
117
|
end
|
294
118
|
end
|
@@ -2,66 +2,54 @@ module Mobilize
|
|
2
2
|
class Job
|
3
3
|
include Mongoid::Document
|
4
4
|
include Mongoid::Timestamps
|
5
|
+
include Mobilize::JobHelper
|
5
6
|
field :path, type: String
|
6
7
|
field :active, type: Boolean
|
7
8
|
field :trigger, type: String
|
8
9
|
|
9
10
|
index({ path: 1})
|
10
11
|
|
11
|
-
def name
|
12
|
-
j = self
|
13
|
-
j.path.split("/").last
|
14
|
-
end
|
15
|
-
|
16
|
-
def stages
|
17
|
-
j = self
|
18
|
-
#starts with the job path, followed by a slash
|
19
|
-
Stage.where(:path=>/^#{j.path.escape_regex}\//).to_a.sort_by{|s| s.path}
|
20
|
-
end
|
21
|
-
|
22
12
|
def Job.find_or_create_by_path(path)
|
23
13
|
j = Job.where(:path=>path).first
|
24
14
|
j = Job.create(:path=>path) unless j
|
25
15
|
return j
|
26
16
|
end
|
27
17
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
j
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
j = self
|
64
|
-
j.stages.select{|s| s.is_working?}.compact.length>0
|
18
|
+
#takes a hash of job parameters (name, active, trigger, stages)
|
19
|
+
#and creates/updates a job with it
|
20
|
+
def Job.update_by_user_name_and_hash(user_name,hash)
|
21
|
+
u = User.where(name: user_name).first
|
22
|
+
r = u.runner
|
23
|
+
j = Job.find_or_create_by_path("#{r.path}/#{hash['name']}")
|
24
|
+
#update top line params
|
25
|
+
j.update_attributes(:active => hash['active'],
|
26
|
+
:trigger => hash['trigger'])
|
27
|
+
(1..5).to_a.each do |s_idx|
|
28
|
+
stage_string = hash["stage#{s_idx.to_s}"]
|
29
|
+
s = Stage.find_by_path("#{j.path}/stage#{s_idx.to_s}")
|
30
|
+
if stage_string.to_s.length==0
|
31
|
+
#delete this stage and all stages after
|
32
|
+
if s
|
33
|
+
j = s.job
|
34
|
+
j.stages[(s.idx-1)..-1].each{|ps| ps.delete}
|
35
|
+
#just in case
|
36
|
+
s.delete
|
37
|
+
end
|
38
|
+
break
|
39
|
+
elsif s.nil?
|
40
|
+
#create this stage
|
41
|
+
s = Stage.find_or_create_by_path("#{j.path}/stage#{s_idx.to_s}")
|
42
|
+
end
|
43
|
+
#parse command string, update stage with it
|
44
|
+
s_handler, call, param_string = [""*3]
|
45
|
+
stage_string.split(" ").ie do |spls|
|
46
|
+
s_handler = spls.first.split(".").first
|
47
|
+
call = spls.first.split(".").last
|
48
|
+
param_string = spls[1..-1].join(" ").strip
|
49
|
+
end
|
50
|
+
s.update_attributes(:call=>call, :handler=>s_handler, :param_string=>param_string)
|
51
|
+
end
|
52
|
+
return j.reload
|
65
53
|
end
|
66
54
|
|
67
55
|
def is_due?
|