kuroko2 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/app/controllers/kuroko2/api/application_controller.rb +4 -0
- data/app/controllers/kuroko2/api/job_definitions_controller.rb +64 -0
- data/app/controllers/kuroko2/job_definitions_controller.rb +9 -2
- data/app/errors/http/unprocessable_entity.rb +4 -0
- data/app/models/kuroko2/api/job_definition_resource.rb +11 -0
- data/app/models/kuroko2/job_definition.rb +1 -1
- data/app/views/kuroko2/job_definitions/_alert.html.slim +1 -1
- data/app/views/kuroko2/job_definitions/_list.html.slim +4 -1
- data/app/views/kuroko2/job_definitions/_search_results.html.slim +4 -1
- data/app/views/kuroko2/job_definitions/show.html.slim +4 -2
- data/app/views/kuroko2/job_timelines/dataset.json.jbuilder +1 -1
- data/app/views/kuroko2/users/index.html.slim +1 -1
- data/config/routes.rb +2 -2
- data/db/migrate/030_add_notify_back_to_normal.rb +5 -0
- data/lib/autoload/kuroko2/workflow/engine.rb +6 -2
- data/lib/autoload/kuroko2/workflow/notifier/concerns/chat_message_builder.rb +4 -0
- data/lib/autoload/kuroko2/workflow/notifier/hipchat.rb +5 -0
- data/lib/autoload/kuroko2/workflow/notifier/mail.rb +4 -0
- data/lib/autoload/kuroko2/workflow/notifier/slack.rb +7 -0
- data/lib/autoload/kuroko2/workflow/notifier/webhook.rb +10 -0
- data/lib/kuroko2/version.rb +1 -1
- data/spec/controllers/job_definitions_controller_spec.rb +62 -0
- data/spec/dummy/db/schema.rb +133 -132
- data/spec/dummy/log/test.log +667 -0
- data/spec/features/job_instance_spec.rb +4 -5
- data/spec/requests/api/job_definitions_spec.rb +178 -0
- data/spec/workflow/engine_spec.rb +2 -0
- data/spec/workflow/notifier/hipchat_spec.rb +11 -0
- data/spec/workflow/notifier/mail_spec.rb +8 -0
- data/spec/workflow/notifier/slack_spec.rb +9 -0
- data/spec/workflow/notifier/webhook_spec.rb +11 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80baa8f9a1ca15294cc73f9f726f5584433d6acb
|
4
|
+
data.tar.gz: 57be564404077de0d32b829687cc579ee925a02f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e657c7824576cecaa2e3cbc2a01abdad723efe66f4dd6da7fa0fe4f68f215f8f46dc3ca3ed7982bb79fb299d736d2363dda21846e604aa61e5c8df03dde934f
|
7
|
+
data.tar.gz: 296957b071325388c8407d6dabeaabe85b1d6ce1498db6f0d80af9eefb4ed2c161c2e17f5592978057189751d5809b579bcfb00e84ccf040329b20594f7513b3
|
data/README.md
CHANGED
@@ -15,6 +15,10 @@ class Kuroko2::Api::ApplicationController < ActionController::Base
|
|
15
15
|
respond_with_error(401, 'unauthorized', exception.message)
|
16
16
|
end
|
17
17
|
|
18
|
+
rescue_from HTTP::UnprocessableEntity do |exception|
|
19
|
+
respond_with_error(422, 'unprocessable_entity', exception.message)
|
20
|
+
end
|
21
|
+
|
18
22
|
rescue_from WeakParameters::ValidationError do |exception|
|
19
23
|
respond_with_error(400, 'bad_request', exception.message)
|
20
24
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Kuroko2::Api::JobDefinitionsController < Kuroko2::Api::ApplicationController
|
2
|
+
include Garage::RestfulActions
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def require_resources
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_resource
|
10
|
+
definition = Kuroko2::JobDefinition.new(definition_params(params))
|
11
|
+
user_ids = admin_id_params(params)
|
12
|
+
definition.admins = Kuroko2::User.active.with(user_ids)
|
13
|
+
|
14
|
+
if definition.save
|
15
|
+
definition.admins.each do |user|
|
16
|
+
user.stars.create(job_definition: definition) if user.google_account?
|
17
|
+
end
|
18
|
+
|
19
|
+
@resource = Kuroko2::Api::JobDefinitionResource.new(definition)
|
20
|
+
else
|
21
|
+
raise HTTP::UnprocessableEntity.new("#{definition.name}: #{definition.errors.full_messages.join()}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def require_resource
|
26
|
+
definition = Kuroko2::JobDefinition.find(params[:id])
|
27
|
+
@resource = Kuroko2::Api::JobDefinitionResource.new(definition)
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_resource
|
31
|
+
definition = Kuroko2::JobDefinition.find(params[:id])
|
32
|
+
|
33
|
+
if definition.update(definition_params(params))
|
34
|
+
@resource = Kuroko2::Api::JobDefinitionResource.new(definition)
|
35
|
+
else
|
36
|
+
raise HTTP::UnprocessableEntity.new("#{definition.name}: #{definition.errors.full_messages.join()}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def definition_params(params)
|
41
|
+
params.permit(
|
42
|
+
:name,
|
43
|
+
:description,
|
44
|
+
:script,
|
45
|
+
:notify_cancellation,
|
46
|
+
:hipchat_room,
|
47
|
+
:hipchat_notify_finished,
|
48
|
+
:suspended,
|
49
|
+
:prevent_multi,
|
50
|
+
:prevent_multi_on_failure,
|
51
|
+
:hipchat_additional_text,
|
52
|
+
:text_tags,
|
53
|
+
:api_allowed,
|
54
|
+
:slack_channel,
|
55
|
+
:webhook_url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def admin_id_params(params)
|
59
|
+
params.permit(user_id: []).
|
60
|
+
try!(:[], :user_id).
|
61
|
+
try!(:reject, &:blank?).
|
62
|
+
try!(:map, &:to_i) || []
|
63
|
+
end
|
64
|
+
end
|
@@ -33,8 +33,15 @@ class Kuroko2::JobDefinitionsController < Kuroko2::ApplicationController
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def new
|
36
|
-
|
37
|
-
|
36
|
+
dup_from = Kuroko2::JobDefinition.find_by(id: params[:dup_from])
|
37
|
+
if dup_from.present?
|
38
|
+
@definition = dup_from.dup
|
39
|
+
@definition.admins = dup_from.admins
|
40
|
+
@definition.tags = dup_from.tags
|
41
|
+
else
|
42
|
+
@definition = Kuroko2::JobDefinition.new
|
43
|
+
end
|
44
|
+
@definition.admins << current_user unless @definition.admins.include?(current_user)
|
38
45
|
end
|
39
46
|
|
40
47
|
def create
|
@@ -1,7 +1,7 @@
|
|
1
1
|
- if @definition.errors.any?
|
2
2
|
.alert.alert-danger
|
3
3
|
i.fa.fa-ban
|
4
|
-
h4 #{pluralize(@definition.errors.count, "error")} prohibited this
|
4
|
+
h4 #{pluralize(@definition.errors.count, "error")} prohibited this job definition from being saved:
|
5
5
|
ul
|
6
6
|
- @definition.errors.full_messages.each do |message|
|
7
7
|
li= message
|
@@ -12,7 +12,10 @@
|
|
12
12
|
- for definition in definitions
|
13
13
|
tr
|
14
14
|
td= definition.id
|
15
|
-
td.no-decorate
|
15
|
+
td.no-decorate
|
16
|
+
- if definition.suspended
|
17
|
+
span.label.label-warning.spacer-right-3 SUSPENDED
|
18
|
+
= link_to definition.name, definition
|
16
19
|
- if !definition.suspended? && !definition.job_schedules.empty?
|
17
20
|
- next_job_schedule = definition.job_schedules.map(&:next).min
|
18
21
|
- if next_job_schedule
|
@@ -34,7 +34,10 @@
|
|
34
34
|
span.star-holder
|
35
35
|
= star_link_for(definition)
|
36
36
|
td= definition.id
|
37
|
-
td.no-decorate
|
37
|
+
td.no-decorate
|
38
|
+
- if definition.suspended
|
39
|
+
span.label.label-warning.spacer-right-3 SUSPENDED
|
40
|
+
= link_to definition.name, definition
|
38
41
|
td.no-decorate
|
39
42
|
- definition.admins.each do |user|
|
40
43
|
= link_to user.name, user_path(user)
|
@@ -80,9 +80,11 @@
|
|
80
80
|
|
81
81
|
.box-footer
|
82
82
|
.row
|
83
|
-
.col-md-
|
83
|
+
.col-md-4
|
84
84
|
= link_to 'Edit Job definition', edit_job_definition_path(@definition), class: 'btn btn-default btn-block', role: 'button'
|
85
|
-
.col-md-
|
85
|
+
.col-md-4
|
86
|
+
= link_to 'Duplicate Job definition', new_job_definition_path(dup_from: @definition.id), class: 'btn btn-default btn-block', role: 'button'
|
87
|
+
.col-md-4
|
86
88
|
= link_to 'Destroy Job definition', @definition, method: :delete, class: 'btn btn-default btn-block', role: 'button', data: { confirm: 'Are you sure?' }
|
87
89
|
.col-md-5#schedules-holder
|
88
90
|
= render template: 'kuroko2/job_schedules/index'
|
@@ -3,7 +3,7 @@ json.end @end_at.strftime('%Y-%m-%d %H:%M:%S')
|
|
3
3
|
json.data do
|
4
4
|
json.array! @instances do |instance|
|
5
5
|
json.id instance.id
|
6
|
-
json.content "<a href='#{job_definition_job_instance_path(instance.job_definition, instance)}'>##{instance.job_definition.id} #{instance.job_definition.name}</a>"
|
6
|
+
json.content "<a href='#{job_definition_job_instance_path(instance.job_definition, instance)}'>##{instance.job_definition.id} #{html_escape(instance.job_definition.name)}</a>"
|
7
7
|
json.start instance.created_at.strftime('%Y-%m-%d %H:%M:%S')
|
8
8
|
json.end (instance.error_at || instance.canceled_at || instance.finished_at || Time.current).try!(:strftime, '%Y-%m-%d %H:%M:%S')
|
9
9
|
json.group instance.job_definition.id
|
@@ -16,7 +16,7 @@
|
|
16
16
|
- if @user.errors.any?
|
17
17
|
.alert.alert-danger
|
18
18
|
i.fa.fa-ban
|
19
|
-
h4 #{pluralize(@user.errors.count, "error")} prohibited this
|
19
|
+
h4 #{pluralize(@user.errors.count, "error")} prohibited this user from being saved:
|
20
20
|
ul
|
21
21
|
- @user.errors.full_messages.each do |message|
|
22
22
|
li= message
|
data/config/routes.rb
CHANGED
@@ -42,8 +42,8 @@ Kuroko2::Engine.routes.draw do
|
|
42
42
|
get '/osd' => 'dashboard#osd', as: :osd
|
43
43
|
|
44
44
|
scope :v1, module: 'api', as: 'api' do
|
45
|
-
resources :job_definitions, path: 'definitions', only:
|
46
|
-
resources :job_instances, path: 'instances', only:
|
45
|
+
resources :job_definitions, path: 'definitions', only: %w(create show update) do
|
46
|
+
resources :job_instances, path: 'instances', only: %w(show create)
|
47
47
|
end
|
48
48
|
|
49
49
|
namespace :stats do
|
@@ -25,7 +25,7 @@ module Kuroko2
|
|
25
25
|
node = extract_node(token)
|
26
26
|
|
27
27
|
message = "(token #{token.uuid}) Retry current node: '#{node.type}: #{node.option}'"
|
28
|
-
token.job_instance.
|
28
|
+
token.job_instance.update_columns(error_at: nil, retrying: true)
|
29
29
|
token.job_instance.logs.info(message)
|
30
30
|
|
31
31
|
token.mark_as_working
|
@@ -119,7 +119,11 @@ module Kuroko2
|
|
119
119
|
token.mark_as_finished
|
120
120
|
unless token.parent
|
121
121
|
token.job_instance.touch(:finished_at)
|
122
|
-
|
122
|
+
if token.job_instance.retrying?
|
123
|
+
Notifier.notify(:back_to_normal, token.job_instance)
|
124
|
+
else
|
125
|
+
Notifier.notify(:finished, token.job_instance)
|
126
|
+
end
|
123
127
|
token.destroy!
|
124
128
|
end
|
125
129
|
end
|
@@ -79,6 +79,11 @@ module Kuroko2
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
def notify_back_to_normal
|
83
|
+
message = build_message(level: 'SUCCESS', text: message_builder.back_to_normal_text)
|
84
|
+
send_to_hipchat(message)
|
85
|
+
end
|
86
|
+
|
82
87
|
def notify_long_elapsed_time
|
83
88
|
message = build_message(level: 'WARNING', text: message_builder.long_elapsed_time_text)
|
84
89
|
send_to_hipchat(message, color: 'red')
|
@@ -88,6 +88,13 @@ module Kuroko2
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
+
def notify_back_to_normal
|
92
|
+
send_attachment_message_to_slack(
|
93
|
+
level: 'SUCCESS',
|
94
|
+
text: message_builder.back_to_normal_text,
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
91
98
|
def notify_long_elapsed_time
|
92
99
|
send_attachment_message_to_slack(
|
93
100
|
level: 'WARNING',
|
@@ -100,6 +100,16 @@ module Kuroko2
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
def notify_back_to_normal
|
104
|
+
request(
|
105
|
+
build_payload(
|
106
|
+
action: 'notify_back_to_normal',
|
107
|
+
level: 'SUCCESS',
|
108
|
+
subject: message_builder.back_to_normal_text,
|
109
|
+
)
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
103
113
|
def notify_long_elapsed_time
|
104
114
|
request(
|
105
115
|
build_payload(
|
data/lib/kuroko2/version.rb
CHANGED
@@ -38,6 +38,68 @@ describe Kuroko2::JobDefinitionsController do
|
|
38
38
|
|
39
39
|
expect(assigns(:definition)).to be_new_record
|
40
40
|
end
|
41
|
+
|
42
|
+
context 'with dup_from params' do
|
43
|
+
subject! { get :new, params: { dup_from: definition.id } }
|
44
|
+
it do
|
45
|
+
expect(response).to have_http_status(:ok)
|
46
|
+
expect(response).to render_template('new')
|
47
|
+
|
48
|
+
expect(assigns(:definition)).to be_new_record
|
49
|
+
expect(assigns(:definition).name).to eq definition.name
|
50
|
+
expect(assigns(:definition).admins).to eq definition.admins + [controller.current_user]
|
51
|
+
expect(assigns(:definition).tags).to eq definition.tags
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with current_user and another admin user' do
|
55
|
+
let!(:admin_user) { create(:user) }
|
56
|
+
let!(:definition) { create(:job_definition, admins: [admin_user, controller.current_user]) }
|
57
|
+
it do
|
58
|
+
expect(response).to have_http_status(:ok)
|
59
|
+
expect(response).to render_template('new')
|
60
|
+
|
61
|
+
expect(assigns(:definition)).to be_new_record
|
62
|
+
expect(assigns(:definition).name).to eq definition.name
|
63
|
+
expect(assigns(:definition).admins).to match_array [admin_user, controller.current_user]
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with only another admin user' do
|
67
|
+
let!(:definition) { create(:job_definition, admins: [admin_user]) }
|
68
|
+
it do
|
69
|
+
expect(response).to have_http_status(:ok)
|
70
|
+
expect(response).to render_template('new')
|
71
|
+
|
72
|
+
expect(assigns(:definition)).to be_new_record
|
73
|
+
expect(assigns(:definition).name).to eq definition.name
|
74
|
+
expect(assigns(:definition).admins).to match_array [admin_user, controller.current_user]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with tags' do
|
80
|
+
let!(:definition) { create(:job_definition, text_tags: 'First,Second') }
|
81
|
+
it do
|
82
|
+
expect(response).to have_http_status(:ok)
|
83
|
+
expect(response).to render_template('new')
|
84
|
+
|
85
|
+
expect(assigns(:definition)).to be_new_record
|
86
|
+
expect(assigns(:definition).name).to eq definition.name
|
87
|
+
expect(assigns(:definition).text_tags).to eq definition.text_tags
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'with invalid id' do
|
92
|
+
subject! { get :new, params: { dup_from: 'invalid' } }
|
93
|
+
it do
|
94
|
+
expect(response).to have_http_status(:ok)
|
95
|
+
expect(response).to render_template('new')
|
96
|
+
|
97
|
+
expect(assigns(:definition)).to be_new_record
|
98
|
+
expect(assigns(:definition).name).to be_blank
|
99
|
+
expect(assigns(:definition).admins).to eq [controller.current_user]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
41
103
|
end
|
42
104
|
|
43
105
|
describe '#create' do
|