kuroko2 0.2.0

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.
Files changed (338) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +15 -0
  4. data/Rakefile +26 -0
  5. data/app/assets/images/kuroko2/avatar.png +0 -0
  6. data/app/assets/images/kuroko2/kuroko-logo-horizontal.png +0 -0
  7. data/app/assets/javascripts/kuroko2/application.js +28 -0
  8. data/app/assets/javascripts/kuroko2/bootstrap.js +2363 -0
  9. data/app/assets/javascripts/kuroko2/definition_linker.js +20 -0
  10. data/app/assets/javascripts/kuroko2/instance_linker.js +10 -0
  11. data/app/assets/javascripts/kuroko2/job_definition_stats.js +67 -0
  12. data/app/assets/javascripts/kuroko2/job_definitions.js +79 -0
  13. data/app/assets/javascripts/kuroko2/job_instances.js +88 -0
  14. data/app/assets/javascripts/kuroko2/job_timelines.js.coffee +24 -0
  15. data/app/assets/javascripts/kuroko2/narrow_job_definitions.js +30 -0
  16. data/app/assets/stylesheets/kuroko2/admin-lte.css +3402 -0
  17. data/app/assets/stylesheets/kuroko2/application.scss +86 -0
  18. data/app/assets/stylesheets/kuroko2/bootstrap.css +6799 -0
  19. data/app/assets/stylesheets/kuroko2/fonts.scss +1 -0
  20. data/app/assets/stylesheets/kuroko2/job_definitions.scss +19 -0
  21. data/app/assets/stylesheets/kuroko2/users.scss +7 -0
  22. data/app/controllers/kuroko2/api/application_controller.rb +49 -0
  23. data/app/controllers/kuroko2/api/job_instances_controller.rb +46 -0
  24. data/app/controllers/kuroko2/api/stats_controller.rb +28 -0
  25. data/app/controllers/kuroko2/application_controller.rb +43 -0
  26. data/app/controllers/kuroko2/dashboard_controller.rb +27 -0
  27. data/app/controllers/kuroko2/execution_logs_controller.rb +19 -0
  28. data/app/controllers/kuroko2/executions_controller.rb +28 -0
  29. data/app/controllers/kuroko2/job_definition_stats_controller.rb +54 -0
  30. data/app/controllers/kuroko2/job_definitions_controller.rb +100 -0
  31. data/app/controllers/kuroko2/job_instances_controller.rb +87 -0
  32. data/app/controllers/kuroko2/job_schedules_controller.rb +39 -0
  33. data/app/controllers/kuroko2/job_suspend_schedules_controller.rb +38 -0
  34. data/app/controllers/kuroko2/job_timelines_controller.rb +56 -0
  35. data/app/controllers/kuroko2/logs_controller.rb +15 -0
  36. data/app/controllers/kuroko2/sessions_controller.rb +32 -0
  37. data/app/controllers/kuroko2/stars_controller.rb +30 -0
  38. data/app/controllers/kuroko2/tokens_controller.rb +47 -0
  39. data/app/controllers/kuroko2/users_controller.rb +62 -0
  40. data/app/controllers/kuroko2/workers_controller.rb +5 -0
  41. data/app/errors/http/bad_request.rb +4 -0
  42. data/app/errors/http/forbidden.rb +4 -0
  43. data/app/errors/http/unauthorized.rb +4 -0
  44. data/app/helpers/kuroko2/application_helper.rb +8 -0
  45. data/app/helpers/kuroko2/dashboard_helper.rb +4 -0
  46. data/app/helpers/kuroko2/executions_helper.rb +4 -0
  47. data/app/helpers/kuroko2/job_definitions_helper.rb +38 -0
  48. data/app/helpers/kuroko2/job_instances_helper.rb +71 -0
  49. data/app/helpers/kuroko2/job_schedules_helper.rb +4 -0
  50. data/app/helpers/kuroko2/logs_helper.rb +4 -0
  51. data/app/helpers/kuroko2/sessions_helper.rb +4 -0
  52. data/app/helpers/kuroko2/stars_helper.rb +4 -0
  53. data/app/helpers/kuroko2/tokens_helper.rb +4 -0
  54. data/app/helpers/kuroko2/users_helper.rb +4 -0
  55. data/app/helpers/kuroko2/workers_helper.rb +4 -0
  56. data/app/jobs/kuroko2/application_job.rb +4 -0
  57. data/app/mailers/kuroko2/application_mailer.rb +6 -0
  58. data/app/mailers/kuroko2/notifications.rb +63 -0
  59. data/app/models/concerns/kuroko2/table_name_customizable.rb +16 -0
  60. data/app/models/kuroko2/admin_assignment.rb +6 -0
  61. data/app/models/kuroko2/api/application_resource.rb +10 -0
  62. data/app/models/kuroko2/api/job_instance_resource.rb +7 -0
  63. data/app/models/kuroko2/application_record.rb +5 -0
  64. data/app/models/kuroko2/execution.rb +55 -0
  65. data/app/models/kuroko2/job_definition.rb +147 -0
  66. data/app/models/kuroko2/job_definition_tag.rb +6 -0
  67. data/app/models/kuroko2/job_instance.rb +118 -0
  68. data/app/models/kuroko2/job_schedule.rb +93 -0
  69. data/app/models/kuroko2/job_suspend_schedule.rb +35 -0
  70. data/app/models/kuroko2/log.rb +3 -0
  71. data/app/models/kuroko2/memory_consumption_log.rb +49 -0
  72. data/app/models/kuroko2/memory_expectancy.rb +21 -0
  73. data/app/models/kuroko2/process_signal.rb +14 -0
  74. data/app/models/kuroko2/star.rb +6 -0
  75. data/app/models/kuroko2/tag.rb +8 -0
  76. data/app/models/kuroko2/tick.rb +12 -0
  77. data/app/models/kuroko2/token.rb +101 -0
  78. data/app/models/kuroko2/user.rb +48 -0
  79. data/app/models/kuroko2/worker.rb +12 -0
  80. data/app/views/kaminari/history/_paginator.html.slim +15 -0
  81. data/app/views/kaminari/list/_paginator.html.slim +17 -0
  82. data/app/views/kuroko2/dashboard/_taglist.html.slim +13 -0
  83. data/app/views/kuroko2/dashboard/index.html.slim +49 -0
  84. data/app/views/kuroko2/execution_logs/index.json.jbuilder +16 -0
  85. data/app/views/kuroko2/executions/index.html.slim +35 -0
  86. data/app/views/kuroko2/job_definition_stats/execution_time.json.jbuilder +13 -0
  87. data/app/views/kuroko2/job_definition_stats/index.html.slim +48 -0
  88. data/app/views/kuroko2/job_definition_stats/memory.json.jbuilder +10 -0
  89. data/app/views/kuroko2/job_definitions/_alert.html.slim +7 -0
  90. data/app/views/kuroko2/job_definitions/_form.html.slim +93 -0
  91. data/app/views/kuroko2/job_definitions/_list.html.slim +26 -0
  92. data/app/views/kuroko2/job_definitions/_search_results.html.slim +51 -0
  93. data/app/views/kuroko2/job_definitions/_taglist.html.slim +13 -0
  94. data/app/views/kuroko2/job_definitions/edit.html.slim +15 -0
  95. data/app/views/kuroko2/job_definitions/index.html.slim +11 -0
  96. data/app/views/kuroko2/job_definitions/new.html.slim +12 -0
  97. data/app/views/kuroko2/job_definitions/show.html.slim +90 -0
  98. data/app/views/kuroko2/job_instances/_instance.html.slim +42 -0
  99. data/app/views/kuroko2/job_instances/index.html.slim +58 -0
  100. data/app/views/kuroko2/job_instances/show.html.slim +19 -0
  101. data/app/views/kuroko2/job_instances/working.html.slim +37 -0
  102. data/app/views/kuroko2/job_schedules/index.html.slim +32 -0
  103. data/app/views/kuroko2/job_suspend_schedules/index.html.slim +27 -0
  104. data/app/views/kuroko2/job_timelines/dataset.json.jbuilder +11 -0
  105. data/app/views/kuroko2/job_timelines/index.html.slim +31 -0
  106. data/app/views/kuroko2/kaminari/history/_paginator.html.slim +15 -0
  107. data/app/views/kuroko2/kaminari/list/_paginator.html.slim +17 -0
  108. data/app/views/kuroko2/layouts/application.html.slim +68 -0
  109. data/app/views/kuroko2/logs/index.html.slim +33 -0
  110. data/app/views/kuroko2/notifications/executor_not_assigned.text.erb +22 -0
  111. data/app/views/kuroko2/notifications/job_failure.html.slim +21 -0
  112. data/app/views/kuroko2/notifications/job_failure.text.erb +18 -0
  113. data/app/views/kuroko2/notifications/notify_long_elapsed_time.text.erb +9 -0
  114. data/app/views/kuroko2/notifications/process_absence.text.erb +22 -0
  115. data/app/views/kuroko2/notifications/remind_failure.html.slim +21 -0
  116. data/app/views/kuroko2/notifications/remind_failure.text.erb +10 -0
  117. data/app/views/kuroko2/sessions/new.html.slim +20 -0
  118. data/app/views/kuroko2/tokens/index.html.slim +42 -0
  119. data/app/views/kuroko2/users/index.html.slim +55 -0
  120. data/app/views/kuroko2/users/show.html.slim +76 -0
  121. data/app/views/kuroko2/workers/index.html.slim +40 -0
  122. data/app/views/layouts/kuroko2/application.html.slim +72 -0
  123. data/app/views/layouts/mailer.html.erb +13 -0
  124. data/app/views/layouts/mailer.text.erb +1 -0
  125. data/bin/cleanup_old_instances.rb +9 -0
  126. data/bin/remind_failure.rb +5 -0
  127. data/config/initializers/000_kuroko2.rb +16 -0
  128. data/config/initializers/assets.rb +9 -0
  129. data/config/initializers/garage.rb +2 -0
  130. data/config/initializers/kaminari_config.rb +3 -0
  131. data/config/initializers/omniauth.rb +5 -0
  132. data/config/locales/en.yml +28 -0
  133. data/config/routes.rb +54 -0
  134. data/db/migrate/001_create_job_definitions.rb +22 -0
  135. data/db/migrate/002_create_job_instances.rb +17 -0
  136. data/db/migrate/003_create_job_schedules.rb +14 -0
  137. data/db/migrate/004_create_ticks.rb +7 -0
  138. data/db/migrate/005_create_logs.rb +13 -0
  139. data/db/migrate/006_create_tokens.rb +21 -0
  140. data/db/migrate/007_create_executions.rb +26 -0
  141. data/db/migrate/008_create_process_signals.rb +15 -0
  142. data/db/migrate/009_create_users.rb +20 -0
  143. data/db/migrate/010_create_admin_assignments.rb +12 -0
  144. data/db/migrate/011_create_stars.rb +12 -0
  145. data/db/migrate/012_create_workers.rb +15 -0
  146. data/db/migrate/018_create_job_definition_tags.rb +13 -0
  147. data/db/migrate/019_create_tags.rb +11 -0
  148. data/db/migrate/021_create_memory_expectancies.rb +17 -0
  149. data/db/migrate/025_create_job_suspend_schedules.rb +12 -0
  150. data/lib/kuroko2/command/executor.rb +62 -0
  151. data/lib/kuroko2/command/kill.rb +24 -0
  152. data/lib/kuroko2/command/monitor.rb +109 -0
  153. data/lib/kuroko2/command/shell.rb +163 -0
  154. data/lib/kuroko2/configuration.rb +19 -0
  155. data/lib/kuroko2/engine.rb +59 -0
  156. data/lib/kuroko2/execution_logger/cloud_watch_logs.rb +92 -0
  157. data/lib/kuroko2/execution_logger/void.rb +13 -0
  158. data/lib/kuroko2/execution_logger.rb +20 -0
  159. data/lib/kuroko2/memory_sampler.rb +50 -0
  160. data/lib/kuroko2/return_to_validator.rb +14 -0
  161. data/lib/kuroko2/servers/base.rb +30 -0
  162. data/lib/kuroko2/servers/command_executor.rb +27 -0
  163. data/lib/kuroko2/servers/job_scheduler.rb +25 -0
  164. data/lib/kuroko2/servers/workflow_processor.rb +25 -0
  165. data/lib/kuroko2/util/logger.rb +19 -0
  166. data/lib/kuroko2/util/rails_logger_formatter.rb +9 -0
  167. data/lib/kuroko2/version.rb +3 -0
  168. data/lib/kuroko2/workflow/assertion_error.rb +6 -0
  169. data/lib/kuroko2/workflow/engine.rb +141 -0
  170. data/lib/kuroko2/workflow/engine_error.rb +6 -0
  171. data/lib/kuroko2/workflow/node.rb +124 -0
  172. data/lib/kuroko2/workflow/notifier/concerns/chat_message_builder.rb +39 -0
  173. data/lib/kuroko2/workflow/notifier/hipchat.rb +88 -0
  174. data/lib/kuroko2/workflow/notifier/mail.rb +44 -0
  175. data/lib/kuroko2/workflow/notifier/slack.rb +121 -0
  176. data/lib/kuroko2/workflow/notifier.rb +31 -0
  177. data/lib/kuroko2/workflow/processor.rb +40 -0
  178. data/lib/kuroko2/workflow/scheduler.rb +42 -0
  179. data/lib/kuroko2/workflow/script_parser.rb +66 -0
  180. data/lib/kuroko2/workflow/shell_scanner.rb +34 -0
  181. data/lib/kuroko2/workflow/syntax_error.rb +6 -0
  182. data/lib/kuroko2/workflow/task/auto_skip_error.rb +20 -0
  183. data/lib/kuroko2/workflow/task/base.rb +32 -0
  184. data/lib/kuroko2/workflow/task/env.rb +45 -0
  185. data/lib/kuroko2/workflow/task/execute.rb +128 -0
  186. data/lib/kuroko2/workflow/task/expected_time.rb +9 -0
  187. data/lib/kuroko2/workflow/task/fork.rb +45 -0
  188. data/lib/kuroko2/workflow/task/kuroko_runner.rb +24 -0
  189. data/lib/kuroko2/workflow/task/noop.rb +13 -0
  190. data/lib/kuroko2/workflow/task/queue.rb +27 -0
  191. data/lib/kuroko2/workflow/task/rails_env.rb +24 -0
  192. data/lib/kuroko2/workflow/task/sequence.rb +13 -0
  193. data/lib/kuroko2/workflow/task/sleep.rb +29 -0
  194. data/lib/kuroko2/workflow/task/sub_process.rb +53 -0
  195. data/lib/kuroko2/workflow/task/time_base.rb +44 -0
  196. data/lib/kuroko2/workflow/task/timeout.rb +9 -0
  197. data/lib/kuroko2/workflow/task/wait.rb +143 -0
  198. data/lib/kuroko2.rb +26 -0
  199. data/lib/tasks/kuroko2_tasks.rake +4 -0
  200. data/spec/command/kill_spec.rb +20 -0
  201. data/spec/command/monitor_spec.rb +68 -0
  202. data/spec/command/shell_spec.rb +87 -0
  203. data/spec/controllers/dashboard_controller_spec.rb +5 -0
  204. data/spec/controllers/executions_controller_spec.rb +23 -0
  205. data/spec/controllers/job_definition_stats_controller_spec.rb +95 -0
  206. data/spec/controllers/job_definitions_controller_spec.rb +89 -0
  207. data/spec/controllers/job_instances_controller_spec.rb +62 -0
  208. data/spec/controllers/job_schedules_controller_spec.rb +39 -0
  209. data/spec/controllers/job_suspend_schedules_controller_spec.rb +39 -0
  210. data/spec/controllers/job_timelines_controller_spec.rb +114 -0
  211. data/spec/controllers/logs_controller_spec.rb +5 -0
  212. data/spec/controllers/sessions_controller_spec.rb +58 -0
  213. data/spec/controllers/stars_controller_spec.rb +28 -0
  214. data/spec/controllers/tokens_controller_spec.rb +5 -0
  215. data/spec/controllers/users_controller_spec.rb +51 -0
  216. data/spec/controllers/workers_controller_spec.rb +5 -0
  217. data/spec/dummy/Rakefile +6 -0
  218. data/spec/dummy/app/assets/config/manifest.js +5 -0
  219. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  220. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  221. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  222. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  223. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  224. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  225. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  226. data/spec/dummy/app/jobs/application_job.rb +2 -0
  227. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  228. data/spec/dummy/app/models/application_record.rb +3 -0
  229. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  230. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  231. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  232. data/spec/dummy/bin/bundle +3 -0
  233. data/spec/dummy/bin/rails +4 -0
  234. data/spec/dummy/bin/rake +4 -0
  235. data/spec/dummy/bin/setup +34 -0
  236. data/spec/dummy/bin/update +29 -0
  237. data/spec/dummy/config/application.rb +25 -0
  238. data/spec/dummy/config/boot.rb +3 -0
  239. data/spec/dummy/config/cable.yml +9 -0
  240. data/spec/dummy/config/database.yml +29 -0
  241. data/spec/dummy/config/environment.rb +5 -0
  242. data/spec/dummy/config/environments/development.rb +54 -0
  243. data/spec/dummy/config/environments/production.rb +86 -0
  244. data/spec/dummy/config/environments/test.rb +42 -0
  245. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  246. data/spec/dummy/config/initializers/assets.rb +11 -0
  247. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  248. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  249. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  250. data/spec/dummy/config/initializers/inflections.rb +16 -0
  251. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  252. data/spec/dummy/config/initializers/new_framework_defaults.rb +23 -0
  253. data/spec/dummy/config/initializers/session_store.rb +3 -0
  254. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  255. data/spec/dummy/config/kuroko2.yml +35 -0
  256. data/spec/dummy/config/locales/en.yml +23 -0
  257. data/spec/dummy/config/puma.rb +47 -0
  258. data/spec/dummy/config/routes.rb +3 -0
  259. data/spec/dummy/config/secrets.yml +22 -0
  260. data/spec/dummy/config/spring.rb +6 -0
  261. data/spec/dummy/config.ru +5 -0
  262. data/spec/dummy/db/schema.rb +217 -0
  263. data/spec/dummy/lib/dummy_extention.rb +14 -0
  264. data/spec/dummy/lib/kuroko2/workflow/task/custom_task1.rb +13 -0
  265. data/spec/dummy/public/404.html +67 -0
  266. data/spec/dummy/public/422.html +67 -0
  267. data/spec/dummy/public/500.html +66 -0
  268. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  269. data/spec/dummy/public/apple-touch-icon.png +0 -0
  270. data/spec/dummy/public/favicon.ico +0 -0
  271. data/spec/execution_logger/cloud_watch_logs_spec.rb +95 -0
  272. data/spec/factories/execution_factory.rb +13 -0
  273. data/spec/factories/job_definition_factory.rb +21 -0
  274. data/spec/factories/job_instance_factory.rb +4 -0
  275. data/spec/factories/job_schedule_factory.rb +10 -0
  276. data/spec/factories/job_suspend_schedule_factory.rb +8 -0
  277. data/spec/factories/memory_expectancy_factory.rb +5 -0
  278. data/spec/factories/process_signal_factory.rb +4 -0
  279. data/spec/factories/star_factory.rb +4 -0
  280. data/spec/factories/tick_factory.rb +4 -0
  281. data/spec/factories/token_factory.rb +10 -0
  282. data/spec/factories/user_factory.rb +11 -0
  283. data/spec/factories/worker_factory.rb +8 -0
  284. data/spec/features/dashborad_spec.rb +82 -0
  285. data/spec/features/job_definition_spec.rb +74 -0
  286. data/spec/features/job_instance_spec.rb +94 -0
  287. data/spec/features/sign_in_and_out_spec.rb +17 -0
  288. data/spec/features/users_spec.rb +90 -0
  289. data/spec/features/workers_spec.rb +44 -0
  290. data/spec/helpers/executions_helper_spec.rb +4 -0
  291. data/spec/helpers/job_definition_helper_spec.rb +42 -0
  292. data/spec/helpers/job_schedules_helper_spec.rb +4 -0
  293. data/spec/helpers/logs_helper_spec.rb +4 -0
  294. data/spec/helpers/tokens_helper_spec.rb +4 -0
  295. data/spec/helpers/users_helper_spec.rb +4 -0
  296. data/spec/helpers/workers_helper_spec.rb +4 -0
  297. data/spec/mailers/notifications_spec.rb +54 -0
  298. data/spec/memory_sampler_spec.rb +11 -0
  299. data/spec/models/admin_assignment_spec.rb +4 -0
  300. data/spec/models/execution_spec.rb +26 -0
  301. data/spec/models/job_definition_spec.rb +163 -0
  302. data/spec/models/job_instance_spec.rb +115 -0
  303. data/spec/models/job_schedule_spec.rb +121 -0
  304. data/spec/models/job_suspend_schedule_spec.rb +32 -0
  305. data/spec/models/memory_consumption_log_spec.rb +50 -0
  306. data/spec/models/memory_expectancy_spec.rb +26 -0
  307. data/spec/models/star_spec.rb +4 -0
  308. data/spec/models/tick_spec.rb +23 -0
  309. data/spec/models/token_spec.rb +54 -0
  310. data/spec/models/user_spec.rb +17 -0
  311. data/spec/models/worker_spec.rb +5 -0
  312. data/spec/rails_helper.rb +81 -0
  313. data/spec/requests/api/job_instances_spec.rb +96 -0
  314. data/spec/requests/api/stats_spec.rb +45 -0
  315. data/spec/return_to_validator_spec.rb +28 -0
  316. data/spec/settings_spec.rb +10 -0
  317. data/spec/spec_helper.rb +49 -0
  318. data/spec/support/feature_sign_in_helper.rb +31 -0
  319. data/spec/support/sign_in_helper.rb +5 -0
  320. data/spec/support/wait_for_ajax.rb +11 -0
  321. data/spec/workflow/engine_spec.rb +241 -0
  322. data/spec/workflow/node_spec.rb +62 -0
  323. data/spec/workflow/notifier/hipchat_spec.rb +117 -0
  324. data/spec/workflow/notifier/mail_spec.rb +86 -0
  325. data/spec/workflow/notifier/slack_spec.rb +110 -0
  326. data/spec/workflow/script_parser_spec.rb +119 -0
  327. data/spec/workflow/shell_scanner_spec.rb +47 -0
  328. data/spec/workflow/task/auto_skip_error_spec.rb +35 -0
  329. data/spec/workflow/task/env_spec.rb +47 -0
  330. data/spec/workflow/task/execute_spec.rb +127 -0
  331. data/spec/workflow/task/expected_time_spec.rb +52 -0
  332. data/spec/workflow/task/fork_spec.rb +30 -0
  333. data/spec/workflow/task/queue_spec.rb +45 -0
  334. data/spec/workflow/task/rails_env_spec.rb +30 -0
  335. data/spec/workflow/task/sleep_spec.rb +22 -0
  336. data/spec/workflow/task/sub_process_spec.rb +32 -0
  337. data/spec/workflow/task/wait_spec.rb +162 -0
  338. metadata +1038 -0
@@ -0,0 +1 @@
1
+ @import url('//fonts.googleapis.com/css?family=Inconsolata|Source+Sans+Pro:300,400,600,300italic,400italic,600italic|Homenaje');
@@ -0,0 +1,19 @@
1
+ .description {
2
+ h1 {
3
+ font-size: 16px;
4
+ }
5
+ h2, h3, h4 {
6
+ font-weight: bold;
7
+ font-size: 14px;
8
+ }
9
+ }
10
+
11
+ .star-holder {
12
+ a:link, a:visited, a:hover, a:active {
13
+ color: #444;
14
+ }
15
+ }
16
+
17
+ .script-input {
18
+ font-family: 'Inconsolata';
19
+ }
@@ -0,0 +1,7 @@
1
+ .user-controls {
2
+ text-align: right;
3
+
4
+ a:not(:last-child) {
5
+ margin-right: 5px;
6
+ }
7
+ }
@@ -0,0 +1,49 @@
1
+ class Kuroko2::Api::ApplicationController < ActionController::Base
2
+ include Garage::ControllerHelper
3
+
4
+ before_action :api_authentication
5
+
6
+ rescue_from ActiveRecord::RecordNotFound do |exception|
7
+ respond_with_error(404, 'record_not_found', exception.message)
8
+ end
9
+
10
+ rescue_from HTTP::Forbidden do |exception|
11
+ respond_with_error(403, 'forbidden', exception.message)
12
+ end
13
+
14
+ rescue_from HTTP::Unauthorized do |exception|
15
+ respond_with_error(401, 'unauthorized', exception.message)
16
+ end
17
+
18
+ rescue_from WeakParameters::ValidationError do |exception|
19
+ respond_with_error(400, 'bad_request', exception.message)
20
+ end
21
+
22
+ private
23
+
24
+ # @param [Integer] status_code HTTP status code
25
+ # @param [String] error_code Must be unique
26
+ # @param [String] message Error message for API client, not for end user.
27
+ def respond_with_error(status_code, error_code, message)
28
+ render json: { status_code: status_code, error_code: error_code, message: message }, status: status_code
29
+ end
30
+
31
+ def api_authentication
32
+ service_name = authenticate_with_http_basic do |name, api_key|
33
+ stored = Kuroko2.config.api_basic_authentication_applications.try!(name.to_sym)
34
+ if Rack::Utils.secure_compare(api_key, stored)
35
+ name.to_sym
36
+ else
37
+ nil
38
+ end
39
+ end
40
+
41
+ if service_name.nil?
42
+ raise HTTP::Unauthorized
43
+ end
44
+ end
45
+
46
+ def basic_user_name
47
+ ActionController::HttpAuthentication::Basic.user_name_and_password(request).first
48
+ end
49
+ end
@@ -0,0 +1,46 @@
1
+ class Kuroko2::Api::JobInstancesController < Kuroko2::Api::ApplicationController
2
+ include Garage::RestfulActions
3
+
4
+ validates :create do
5
+ hash :env, description: 'Env variables to launch an instance' do |env|
6
+ env.to_h.all? { |_, v| v.is_a?(String) }
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def require_resources
13
+ protect_resource_as Kuroko2::Api::JobInstanceResource
14
+ end
15
+
16
+ def create_resource
17
+ definition = Kuroko2::JobDefinition.find(params[:job_definition_id])
18
+ unless definition.api_allowed?
19
+ raise HTTP::Forbidden.new("#{definition.name} is not allowed to be executed via API")
20
+ end
21
+
22
+ instance = definition.job_instances.create(
23
+ script: definition.script.prepend(env_script),
24
+ )
25
+ instance.logs.info("Launched by instances API (#{basic_user_name})")
26
+ Kuroko2::Api::JobInstanceResource.new(instance)
27
+ end
28
+
29
+ def require_resource
30
+ instance = Kuroko2::JobInstance.find(params[:id])
31
+ @resource = Kuroko2::Api::JobInstanceResource.new(instance)
32
+ end
33
+
34
+ def env_script
35
+ return '' unless params[:env]
36
+
37
+ params[:env].permit!.to_h.map { |key, value|
38
+ "env: #{key}='#{value.gsub("'", "\\\\'")}'"
39
+ }.join("\n").concat("\n")
40
+ end
41
+
42
+ # Don't set location header
43
+ def location
44
+ nil
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ class Kuroko2::Api::StatsController < Kuroko2::Api::ApplicationController
2
+ skip_before_action :api_authentication
3
+
4
+ COUNT_INSTANCES_SQL = <<-SQL
5
+ SELECT COUNT(error_at IS NULL OR NULL) AS `kuroko2.job_instances.working`,
6
+ COUNT(error_at IS NOT NULL OR NULL) AS `kuroko2.job_instances.error`
7
+ FROM #{Kuroko2::JobInstance.table_name}
8
+ WHERE finished_at IS NULL
9
+ AND canceled_at IS NULL
10
+ SQL
11
+
12
+ def instance
13
+ render json: ActiveRecord::Base.connection.select_one(COUNT_INSTANCES_SQL).to_hash
14
+ end
15
+
16
+ def waiting_execution
17
+ waiting_executions_count = Kuroko2::Execution.select('queue, COUNT(1) AS `count`').
18
+ where('started_at IS NULL AND created_at < ?', 3.minutes.ago).group(:queue)
19
+
20
+ render json: Kuroko2::Worker.pluck(:queue).uniq.inject({}) { |result, queue|
21
+ result.merge(
22
+ "kuroko2.executions.waiting.#{queue}" => waiting_executions_count.find { |count|
23
+ count.queue == queue
24
+ }.try!(:[], "count") || 0
25
+ )
26
+ }
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ class Kuroko2::ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+
6
+ helper_method :current_user, :signed_in?
7
+ before_action :require_sign_in
8
+
9
+ rescue_from HTTP::BadRequest do
10
+ respond_to do |format|
11
+ format.html { render 'public/500.html', layout: false, status: :bad_request }
12
+ format.json { render json: { message: 'Bad Request' }, status: :bad_request }
13
+ end
14
+ end
15
+
16
+ def current_user
17
+ @_current_user ||= begin
18
+ if (id = session[:user_id])
19
+ Kuroko2::User.active.find(id)
20
+ end
21
+ end
22
+ rescue ActiveRecord::RecordNotFound
23
+ reset_session
24
+ redirect_to sign_in_path(return_to: url_for(params.permit!.to_h.merge(only_path: true)))
25
+ end
26
+
27
+ private
28
+
29
+ def current_user=(user)
30
+ session[:user_id] = user.id
31
+ @_current_user = user
32
+ end
33
+
34
+ def signed_in?
35
+ current_user.present?
36
+ end
37
+
38
+ def require_sign_in
39
+ unless signed_in?
40
+ redirect_to sign_in_path(return_to: url_for(params.permit!.to_h.merge(only_path: true)))
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ class Kuroko2::DashboardController < Kuroko2::ApplicationController
2
+ def index
3
+ @definitions = current_user.job_definitions
4
+
5
+ @input_tags = params[:tag] || []
6
+ if @input_tags.present?
7
+ @definitions = @definitions.tagged_by(@input_tags)
8
+ end
9
+
10
+ @instances = Kuroko2::JobInstance.working.where(job_definition: @definitions)
11
+ @related_tags = @definitions.includes(:tags).map(&:tags).flatten.uniq
12
+
13
+ end
14
+
15
+ def osd
16
+ render xml: <<-XML.strip_heredoc
17
+ <?xml version="1.0" encoding="UTF-8" ?>
18
+ <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
19
+ <ShortName>Kuroko2</ShortName>
20
+ <Description>Search Kuroko2</Description>
21
+ <InputEncoding>UTF-8</InputEncoding>
22
+ <Url type="text/html" method="get" template="#{job_definitions_url}?q={searchTerms}"/>
23
+ <Image width="16" height="16" type="image/x-icon">#{root_url}favicon.ico</Image>
24
+ </OpenSearchDescription>
25
+ XML
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ class Kuroko2::ExecutionLogsController < Kuroko2::ApplicationController
2
+ def index
3
+ @definition = Kuroko2::JobDefinition.find(logs_params[:job_definition_id])
4
+ @instance = Kuroko2::JobInstance.find(logs_params[:job_instance_id])
5
+
6
+ execution_logger = Kuroko2::ExecutionLogger.
7
+ get_logger(stream_name: "JOB#{sprintf("%010d", @definition.id)}/#{@instance.id}")
8
+
9
+ @response = execution_logger.get_logs(logs_params[:token])
10
+ rescue Kuroko2::ExecutionLogger::NotFound
11
+ head 404
12
+ end
13
+
14
+ private
15
+
16
+ def logs_params
17
+ params.permit(:job_definition_id, :job_instance_id, :token)
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ class Kuroko2::ExecutionsController < Kuroko2::ApplicationController
2
+
3
+ before_action :set_execution, only: %i(destroy)
4
+
5
+ def index
6
+ @executions = Kuroko2::Execution.where(finished_at: nil).order(created_at: :desc).includes(job_instance: :job_definition)
7
+ end
8
+
9
+ def destroy
10
+ if @execution.try(:pid)
11
+ hostname = Kuroko2::Worker.executing(@execution.id).try(:hostname)
12
+ Kuroko2::ProcessSignal.create!(pid: @execution.pid, hostname: hostname) if hostname
13
+ end
14
+
15
+ redirect_to job_definition_job_instance_path(job_definition_id: execution_params[:job_definition_id], id: execution_params[:job_instance_id])
16
+ end
17
+
18
+ private
19
+
20
+ def set_execution
21
+ @execution = Kuroko2::Execution.where(job_definition_id: execution_params[:job_definition_id], job_instance_id: execution_params[:job_instance_id], id: execution_params[:id]).take
22
+ end
23
+
24
+ def execution_params
25
+ params.permit(:id, :job_definition_id, :job_instance_id)
26
+ end
27
+
28
+ end
@@ -0,0 +1,54 @@
1
+ class Kuroko2::JobDefinitionStatsController < Kuroko2::ApplicationController
2
+ def index
3
+ set_definition
4
+ end
5
+
6
+ def execution_time
7
+ set_definition
8
+ set_period
9
+
10
+ @logs = Kuroko2::JobInstance.where(job_definition_id: params[:job_definition_id]).
11
+ order(created_at: :desc)
12
+ if @start_at
13
+ @logs = @logs.where(created_at: @start_at..@end_at)
14
+ else
15
+ @logs = @logs.limit(10)
16
+ end
17
+ end
18
+
19
+ def memory
20
+ set_definition
21
+ set_period
22
+
23
+ target_instance = Kuroko2::JobInstance.where(job_definition_id: params[:job_definition_id])
24
+ if @start_at
25
+ target_instance = target_instance.where(created_at: @start_at..@end_at)
26
+ end
27
+
28
+ @logs = Kuroko2::MemoryConsumptionLog.joins(:job_instance).
29
+ merge(target_instance).order(created_at: :desc)
30
+ @logs = @logs.limit(10) unless @start_at
31
+ end
32
+
33
+ private
34
+
35
+ def set_period
36
+ @end_at = Time.now
37
+
38
+ @start_at =
39
+ case params[:period]
40
+ when /\A(\d+)d\z/
41
+ $1.to_i.days.ago(@end_at)
42
+ when /\A(\d+)w\z/
43
+ $1.to_i.weeks.ago(@end_at)
44
+ when /\A(\d+)m\z/
45
+ $1.to_i.month.ago(@end_at)
46
+ else
47
+ nil
48
+ end
49
+ end
50
+
51
+ def set_definition
52
+ @definition = Kuroko2::JobDefinition.find(params[:job_definition_id])
53
+ end
54
+ end
@@ -0,0 +1,100 @@
1
+ class Kuroko2::JobDefinitionsController < Kuroko2::ApplicationController
2
+ before_action :set_definition, only: [:show, :edit, :update, :destroy]
3
+
4
+ def index
5
+ rel = Kuroko2::JobDefinition
6
+ query = query_params[:q]
7
+
8
+ if query.present?
9
+ rel = rel.search_by(query)
10
+ end
11
+
12
+ @input_tags = query_params[:tag] || []
13
+ if @input_tags.present?
14
+ rel = rel.tagged_by(@input_tags)
15
+ end
16
+
17
+ if query.present? || @input_tags.present?
18
+ @related_tags = rel.includes(:tags).map(&:tags).flatten.uniq
19
+ else
20
+ @related_tags = Kuroko2::Tag.all
21
+ end
22
+
23
+ @definitions = rel.ordered.page(page_params[:page])
24
+ end
25
+
26
+ def show
27
+ @instances = @definition.job_instances.page(0)
28
+ @schedules = @definition.job_schedules
29
+ @suspend_schedules = @definition.job_suspend_schedules
30
+
31
+ @schedule = Kuroko2::JobSchedule.new(job_definition: @definitions)
32
+ @suspend_schedule = Kuroko2::JobSuspendSchedule.new(job_definition: @definitions)
33
+ end
34
+
35
+ def new
36
+ @definition = Kuroko2::JobDefinition.new
37
+ end
38
+
39
+ def create
40
+ @definition = Kuroko2::JobDefinition.new(definition_params)
41
+ @definition.admins << current_user
42
+
43
+ if @definition.save
44
+ current_user.stars.create(job_definition: @definition)
45
+
46
+ redirect_to @definition, notice: 'Job Definition was successfully created.'
47
+ else
48
+ render :new
49
+ end
50
+ end
51
+
52
+ def edit
53
+ end
54
+
55
+ def update
56
+ success = ActiveRecord::Base.transaction do
57
+ @definition.attributes = definition_params
58
+ @definition.admins = Kuroko2::User.active.with(admin_id_params)
59
+
60
+ @definition.save
61
+ end
62
+
63
+ if success
64
+ redirect_to @definition, notice: 'Job Definition was successfully updated.'
65
+ else
66
+ render :edit
67
+ end
68
+ end
69
+
70
+ def destroy
71
+ @definition.destroy
72
+
73
+ redirect_to job_definitions_path, notice: 'Job Definition was successfully destroyed.'
74
+ end
75
+
76
+ private
77
+
78
+ def admin_id_params
79
+ params.require(:admin_assignments).permit(user_id: []).
80
+ try(:[], :user_id).
81
+ try(:reject!, &:blank?).
82
+ try(:map, &:to_i) || []
83
+ end
84
+
85
+ def definition_params
86
+ params.require(:job_definition).permit(:name, :description, :script, :notify_cancellation, :hipchat_room, :hipchat_notify_finished, :suspended, :prevent_multi, :prevent_multi_on_failure, :hipchat_additional_text, :text_tags, :api_allowed, :slack_channel)
87
+ end
88
+
89
+ def query_params
90
+ params.permit(:q, tag: [])
91
+ end
92
+
93
+ def page_params
94
+ params.permit(:page)
95
+ end
96
+
97
+ def set_definition
98
+ @definition = Kuroko2::JobDefinition.find(params[:id])
99
+ end
100
+ end
@@ -0,0 +1,87 @@
1
+ class Kuroko2::JobInstancesController < Kuroko2::ApplicationController
2
+ before_action :set_definition, only: %i(index create show destroy force_destroy)
3
+ before_action :set_instance, only: %i(show destroy force_destroy)
4
+
5
+ def index
6
+ @instances = @definition.job_instances.page(page_params[:page])
7
+
8
+ render layout: false
9
+ end
10
+
11
+ def create
12
+ if params[:job_definition].present?
13
+ @instance = @definition.job_instances.create(params.require(:job_definition).permit(:script))
14
+ else
15
+ @instance = @definition.job_instances.create
16
+ end
17
+
18
+ if @instance
19
+ @instance.logs.info("Launched by #{current_user.name}.")
20
+
21
+ redirect_to job_definition_job_instance_path(@definition, @instance)
22
+ else
23
+ raise HTTP::BadRequest
24
+ end
25
+ end
26
+
27
+ def show
28
+ @logs = @instance.logs
29
+ @tokens = @instance.tokens
30
+
31
+ if params[:mode] == :naked
32
+ render partial: 'instance', layout: false
33
+ else
34
+ # render
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ if @instance.cancelable?
40
+ ActiveRecord::Base.transaction { @instance.cancel }
41
+
42
+ message = "This job was canceled by #{current_user.name}."
43
+ @instance.logs.warn(message)
44
+ Kuroko2.logger.warn(message)
45
+ end
46
+
47
+ redirect_to job_definition_job_instance_path(@definition, @instance)
48
+ end
49
+
50
+ def force_destroy
51
+ ActiveRecord::Base.transaction do
52
+ @instance.executions.each do |execution|
53
+ execution = Kuroko2::Worker.executing(execution.id)
54
+ execution.update_column(:execution_id, nil) if execution
55
+ end
56
+
57
+ @instance.cancel
58
+ end
59
+
60
+ message = "Force canceled by #{current_user.name}."
61
+ @instance.logs.warn(message)
62
+ Kuroko2.logger.warn(message)
63
+
64
+ redirect_to job_definition_job_instance_path(@definition, @instance)
65
+ end
66
+
67
+ def working
68
+ @instances = Kuroko2::JobInstance.working.order(id: :desc).joins(job_definition: :admins).includes(job_definition: :admins)
69
+ end
70
+
71
+ private
72
+ def job_instance_params
73
+ params.permit(:job_definition_id, :id)
74
+ end
75
+
76
+ def page_params
77
+ params.permit(:page)
78
+ end
79
+
80
+ def set_definition
81
+ @definition = Kuroko2::JobDefinition.find(job_instance_params[:job_definition_id])
82
+ end
83
+
84
+ def set_instance
85
+ @instance = @definition.job_instances.find(job_instance_params[:id])
86
+ end
87
+ end
@@ -0,0 +1,39 @@
1
+ class Kuroko2::JobSchedulesController < Kuroko2::ApplicationController
2
+ before_action :set_definition, only: %i(index create destroy)
3
+
4
+ def index
5
+ @schedules = @definition.job_schedules
6
+ @schedule = Kuroko2::JobSchedule.new
7
+
8
+ render layout: false
9
+ end
10
+
11
+ def create
12
+ schedule = @definition.job_schedules.create(job_schedule_params)
13
+
14
+ if schedule.valid?
15
+ render json: schedule, status: :created
16
+ else
17
+ render json: schedule, status: :bad_request
18
+ end
19
+ end
20
+
21
+ def destroy
22
+ schedule = Kuroko2::JobSchedule.find(params[:id])
23
+ if schedule.destroy
24
+ render json: schedule, status: :ok
25
+ else
26
+ render json: schedule, status: :bad_request
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def job_schedule_params
33
+ params.require(:job_schedule).permit(:cron)
34
+ end
35
+
36
+ def set_definition
37
+ @definition = Kuroko2::JobDefinition.find(params[:job_definition_id])
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ class Kuroko2::JobSuspendSchedulesController < Kuroko2::ApplicationController
2
+ before_action :set_definition, only: %i(index create destroy)
3
+
4
+ def index
5
+ @suspend_schedules = @definition.job_suspend_schedules
6
+ @suspend_schedule = Kuroko2::JobSuspendSchedule.new
7
+ render layout: false
8
+ end
9
+
10
+ def create
11
+ suspend_schedule = @definition.job_suspend_schedules.create(job_suspend_schedule_params)
12
+
13
+ if suspend_schedule.valid?
14
+ render json: suspend_schedule, status: :created
15
+ else
16
+ render json: suspend_schedule, status: :bad_request
17
+ end
18
+ end
19
+
20
+ def destroy
21
+ suspend_schedule = Kuroko2::JobSuspendSchedule.find(params[:id])
22
+ if suspend_schedule.destroy
23
+ render json: suspend_schedule, status: :ok
24
+ else
25
+ render json: suspend_schedule, status: :bad_request
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def job_suspend_schedule_params
32
+ params.require(:job_suspend_schedule).permit(:cron)
33
+ end
34
+
35
+ def set_definition
36
+ @definition = Kuroko2::JobDefinition.find(params[:job_definition_id])
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ class Kuroko2::JobTimelinesController < Kuroko2::ApplicationController
2
+ def index
3
+ find_user
4
+ end
5
+
6
+ def dataset
7
+ find_user
8
+ set_period
9
+
10
+ definition_ids = []
11
+ definition_ids << my_difinitions.pluck(:id)
12
+ definition_ids << assigned_definitions.pluck(:id)
13
+
14
+ @instances = Kuroko2::JobInstance.includes(:job_definition).
15
+ where(job_definition_id: definition_ids.flatten.uniq, created_at: @start_at..@end_at).
16
+ order(:created_at)
17
+ end
18
+
19
+ private
20
+
21
+ def my_difinitions
22
+ rel = @user.job_definitions
23
+ rel = rel.tagged_by(params[:tag]) if params[:tag].present?
24
+ rel
25
+ end
26
+
27
+ def assigned_definitions
28
+ rel = @user.assigned_job_definitions
29
+ rel = rel.tagged_by(params[:tag]) if params[:tag].present?
30
+ rel
31
+ end
32
+
33
+ def find_user
34
+ if params[:user_id]
35
+ @user = Kuroko2::User.find(params[:user_id])
36
+ else
37
+ @user = current_user
38
+ end
39
+ end
40
+
41
+ def set_period
42
+ @end_at = Time.now
43
+
44
+ @start_at =
45
+ case params[:period]
46
+ when /\A(\d+)h\z/
47
+ $1.to_i.hours.ago(@end_at)
48
+ when /\A(\d+)d\z/
49
+ $1.to_i.days.ago(@end_at)
50
+ when /\A(\d+)w\z/
51
+ $1.to_i.weeks.ago(@end_at)
52
+ else
53
+ 1.hour.ago(@end_at)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,15 @@
1
+ class Kuroko2::LogsController < Kuroko2::ApplicationController
2
+ def index
3
+ @definition = Kuroko2::JobDefinition.find(logs_params[:job_definition_id])
4
+ @instance = Kuroko2::JobInstance.find(logs_params[:job_instance_id])
5
+ @logs = @instance.logs
6
+
7
+ render layout: false
8
+ end
9
+
10
+ private
11
+
12
+ def logs_params
13
+ params.permit(:job_definition_id, :job_instance_id)
14
+ end
15
+ end