foreman_patch 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (312) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +38 -0
  4. data/Rakefile +53 -0
  5. data/app/assets/javascript/foreman_patch/plan_edit_windows.js +9 -0
  6. data/app/assets/stylesheets/foreman_patch/cycle_plans.scss +6 -0
  7. data/app/assets/stylesheets/foreman_patch/foreman_patch.css +4 -0
  8. data/app/controllers/concerns/foreman_patch/parameters/ticket_field.rb +26 -0
  9. data/app/controllers/foreman_patch/api/v2/base_controller.rb +12 -0
  10. data/app/controllers/foreman_patch/api/v2/cycles_controller.rb +78 -0
  11. data/app/controllers/foreman_patch/api/v2/groups_controller.rb +70 -0
  12. data/app/controllers/foreman_patch/api/v2/host_groups_controller.rb +13 -0
  13. data/app/controllers/foreman_patch/api/v2/invocations_controller.rb +70 -0
  14. data/app/controllers/foreman_patch/api/v2/plans_controller.rb +79 -0
  15. data/app/controllers/foreman_patch/api/v2/rounds_controller.rb +77 -0
  16. data/app/controllers/foreman_patch/api/v2/window_plans_controller.rb +73 -0
  17. data/app/controllers/foreman_patch/api/v2/windows_controller.rb +85 -0
  18. data/app/controllers/foreman_patch/concerns/api/v2/hosts_controller_extensions.rb +21 -0
  19. data/app/controllers/foreman_patch/concerns/hosts_controller_extensions.rb +61 -0
  20. data/app/controllers/foreman_patch/cycles_controller.rb +34 -0
  21. data/app/controllers/foreman_patch/groups_controller.rb +68 -0
  22. data/app/controllers/foreman_patch/invocations_controller.rb +51 -0
  23. data/app/controllers/foreman_patch/plans_controller.rb +59 -0
  24. data/app/controllers/foreman_patch/rounds_controller.rb +18 -0
  25. data/app/controllers/foreman_patch/ticket_fields_controller.rb +37 -0
  26. data/app/controllers/foreman_patch/window_plans_controller.rb +60 -0
  27. data/app/controllers/foreman_patch/windows_controller.rb +58 -0
  28. data/app/helpers/concerns/foreman_patch/hosts_helper_extensions.rb +13 -0
  29. data/app/helpers/foreman_patch/cycles_helper.rb +19 -0
  30. data/app/helpers/foreman_patch/hosts_helper.rb +52 -0
  31. data/app/helpers/foreman_patch/patching_helper.rb +116 -0
  32. data/app/helpers/foreman_patch/plans_helper.rb +45 -0
  33. data/app/helpers/foreman_patch/ticket_helper.rb +11 -0
  34. data/app/helpers/foreman_patch/window_patching_helper.rb +20 -0
  35. data/app/helpers/foreman_patch/window_plans_helper.rb +13 -0
  36. data/app/helpers/foreman_patch/windows_helper.rb +17 -0
  37. data/app/lib/actions/foreman_patch/cycle/complete.rb +41 -0
  38. data/app/lib/actions/foreman_patch/cycle/create.rb +69 -0
  39. data/app/lib/actions/foreman_patch/cycle/initiate.rb +68 -0
  40. data/app/lib/actions/foreman_patch/cycle/plan.rb +73 -0
  41. data/app/lib/actions/foreman_patch/cycle/prepare_content.rb +123 -0
  42. data/app/lib/actions/foreman_patch/host/reschedule.rb +32 -0
  43. data/app/lib/actions/foreman_patch/invocation/action.rb +135 -0
  44. data/app/lib/actions/foreman_patch/invocation/ensure_services.rb +47 -0
  45. data/app/lib/actions/foreman_patch/invocation/patch.rb +93 -0
  46. data/app/lib/actions/foreman_patch/invocation/reschedule.rb +21 -0
  47. data/app/lib/actions/foreman_patch/invocation/restart.rb +101 -0
  48. data/app/lib/actions/foreman_patch/invocation/update_packages.rb +52 -0
  49. data/app/lib/actions/foreman_patch/invocation/wait_for_host.rb +103 -0
  50. data/app/lib/actions/foreman_patch/round/add_missing_hosts.rb +21 -0
  51. data/app/lib/actions/foreman_patch/round/create.rb +37 -0
  52. data/app/lib/actions/foreman_patch/round/patch.rb +81 -0
  53. data/app/lib/actions/foreman_patch/round/plan.rb +33 -0
  54. data/app/lib/actions/foreman_patch/round/resolve_hosts.rb +45 -0
  55. data/app/lib/actions/foreman_patch/window/create.rb +41 -0
  56. data/app/lib/actions/foreman_patch/window/patch.rb +72 -0
  57. data/app/lib/actions/foreman_patch/window/plan.rb +43 -0
  58. data/app/lib/actions/foreman_patch/window/publish.rb +32 -0
  59. data/app/lib/actions/foreman_patch/window/resolve_hosts.rb +31 -0
  60. data/app/lib/actions/helpers/failure_notification.rb +20 -0
  61. data/app/lib/actions/helpers/with_feature_action.rb +102 -0
  62. data/app/lib/actions/middleware/check_exit_status.rb +31 -0
  63. data/app/mailers/foreman_patch/cycle_mailer.rb +17 -0
  64. data/app/mailers/foreman_patch/group_mailer.rb +41 -0
  65. data/app/mailers/foreman_patch/invocation_mailer.rb +19 -0
  66. data/app/models/foreman_patch/concerns/group_facet_host_extensions.rb +35 -0
  67. data/app/models/foreman_patch/concerns/host_managed_extensions.rb +17 -0
  68. data/app/models/foreman_patch/cycle.rb +49 -0
  69. data/app/models/foreman_patch/group.rb +43 -0
  70. data/app/models/foreman_patch/host/group_facet.rb +13 -0
  71. data/app/models/foreman_patch/invocation.rb +60 -0
  72. data/app/models/foreman_patch/plan.rb +110 -0
  73. data/app/models/foreman_patch/plan_task_group.rb +11 -0
  74. data/app/models/foreman_patch/round.rb +68 -0
  75. data/app/models/foreman_patch/ticket_field.rb +23 -0
  76. data/app/models/foreman_patch/window.rb +123 -0
  77. data/app/models/foreman_patch/window_plan.rb +77 -0
  78. data/app/models/foreman_patch/window_task_group.rb +11 -0
  79. data/app/models/setting/patching.rb +57 -0
  80. data/app/services/foreman_patch/cycle_name_generator.rb +38 -0
  81. data/app/services/foreman_patch/ticket/affected_items.rb +110 -0
  82. data/app/services/foreman_patch/ticket/api.rb +68 -0
  83. data/app/services/foreman_patch/ticket/change_request.rb +92 -0
  84. data/app/services/foreman_patch/ticket/field_render.rb +21 -0
  85. data/app/services/foreman_patch/ticket/payload.rb +136 -0
  86. data/app/services/foreman_patch/ticket.rb +14 -0
  87. data/app/views/dashboard/_foreman_patch_widget.html.erb +2 -0
  88. data/app/views/foreman_patch/api/v2/cycles/base.json.rabl +3 -0
  89. data/app/views/foreman_patch/api/v2/cycles/create.json.rabl +3 -0
  90. data/app/views/foreman_patch/api/v2/cycles/index.json.rabl +3 -0
  91. data/app/views/foreman_patch/api/v2/cycles/show.json.rabl +9 -0
  92. data/app/views/foreman_patch/api/v2/cycles/update.json.rabl +3 -0
  93. data/app/views/foreman_patch/api/v2/group_facet/base.json.rabl +7 -0
  94. data/app/views/foreman_patch/api/v2/group_facet/base_with_root.json.rabl +4 -0
  95. data/app/views/foreman_patch/api/v2/group_facet/show.json.rabl +3 -0
  96. data/app/views/foreman_patch/api/v2/groups/base.json.rabl +3 -0
  97. data/app/views/foreman_patch/api/v2/groups/create.json.rabl +3 -0
  98. data/app/views/foreman_patch/api/v2/groups/index.json.rabl +2 -0
  99. data/app/views/foreman_patch/api/v2/groups/show.json.rabl +14 -0
  100. data/app/views/foreman_patch/api/v2/groups/update.json.rabl +3 -0
  101. data/app/views/foreman_patch/api/v2/invocations/base.json.rabl +6 -0
  102. data/app/views/foreman_patch/api/v2/invocations/index.json.rabl +3 -0
  103. data/app/views/foreman_patch/api/v2/invocations/phase.json.rabl +7 -0
  104. data/app/views/foreman_patch/api/v2/invocations/show.json.rabl +7 -0
  105. data/app/views/foreman_patch/api/v2/plans/base.json.rabl +3 -0
  106. data/app/views/foreman_patch/api/v2/plans/create.json.rabl +2 -0
  107. data/app/views/foreman_patch/api/v2/plans/index.json.rabl +3 -0
  108. data/app/views/foreman_patch/api/v2/plans/show.json.rabl +9 -0
  109. data/app/views/foreman_patch/api/v2/plans/update.json.rabl +2 -0
  110. data/app/views/foreman_patch/api/v2/rounds/base.json.rabl +3 -0
  111. data/app/views/foreman_patch/api/v2/rounds/index.json.rabl +3 -0
  112. data/app/views/foreman_patch/api/v2/rounds/show.json.rabl +17 -0
  113. data/app/views/foreman_patch/api/v2/rounds/status.json.rabl +11 -0
  114. data/app/views/foreman_patch/api/v2/window_plans/base.json.rabl +4 -0
  115. data/app/views/foreman_patch/api/v2/window_plans/create.json.rabl +2 -0
  116. data/app/views/foreman_patch/api/v2/window_plans/index.json.rabl +2 -0
  117. data/app/views/foreman_patch/api/v2/window_plans/show.json.rabl +14 -0
  118. data/app/views/foreman_patch/api/v2/window_plans/update.json.rabl +2 -0
  119. data/app/views/foreman_patch/api/v2/windows/base.json.rabl +3 -0
  120. data/app/views/foreman_patch/api/v2/windows/index.json.rabl +3 -0
  121. data/app/views/foreman_patch/api/v2/windows/schedule.json.rabl +13 -0
  122. data/app/views/foreman_patch/api/v2/windows/show.json.rabl +13 -0
  123. data/app/views/foreman_patch/api/v2/windows/update.json.rabl +3 -0
  124. data/app/views/foreman_patch/cycle_mailer/_details.html.erb +4 -0
  125. data/app/views/foreman_patch/cycle_mailer/_round.html.erb +12 -0
  126. data/app/views/foreman_patch/cycle_mailer/_summary.html.erb +6 -0
  127. data/app/views/foreman_patch/cycle_mailer/_window.html.erb +4 -0
  128. data/app/views/foreman_patch/cycle_mailer/planned.html.erb +7 -0
  129. data/app/views/foreman_patch/cycles/_form.html.erb +9 -0
  130. data/app/views/foreman_patch/cycles/edit.html.erb +41 -0
  131. data/app/views/foreman_patch/cycles/index.html.erb +45 -0
  132. data/app/views/foreman_patch/cycles/show.html.erb +26 -0
  133. data/app/views/foreman_patch/group_mailer/_dashboard.html.erb +31 -0
  134. data/app/views/foreman_patch/group_mailer/_list.html.erb +17 -0
  135. data/app/views/foreman_patch/group_mailer/completed.html.erb +16 -0
  136. data/app/views/foreman_patch/group_mailer/initiated.html.erb +4 -0
  137. data/app/views/foreman_patch/groups/_form.html.erb +9 -0
  138. data/app/views/foreman_patch/groups/edit.html.erb +3 -0
  139. data/app/views/foreman_patch/groups/index.html.erb +40 -0
  140. data/app/views/foreman_patch/groups/new.html.erb +3 -0
  141. data/app/views/foreman_patch/hosts/hosts/new_action.html.erb +1 -0
  142. data/app/views/foreman_patch/hosts/new_action.html.erb +1 -0
  143. data/app/views/foreman_patch/invocation_mailer/_output_line_set.html.erb +6 -0
  144. data/app/views/foreman_patch/invocation_mailer/_output_line_set.text.erb +3 -0
  145. data/app/views/foreman_patch/invocation_mailer/failure.html.erb +50 -0
  146. data/app/views/foreman_patch/invocation_mailer/failure.text.erb +10 -0
  147. data/app/views/foreman_patch/invocations/_output_line_set.html.erb +8 -0
  148. data/app/views/foreman_patch/invocations/_phase.html.erb +17 -0
  149. data/app/views/foreman_patch/invocations/_primary.html.erb +1 -0
  150. data/app/views/foreman_patch/invocations/_refresh.js.erb +7 -0
  151. data/app/views/foreman_patch/invocations/show.html.erb +44 -0
  152. data/app/views/foreman_patch/invocations/show.js.erb +17 -0
  153. data/app/views/foreman_patch/layouts/react.html.erb +17 -0
  154. data/app/views/foreman_patch/plans/_form.html.erb +12 -0
  155. data/app/views/foreman_patch/plans/edit.html.erb +6 -0
  156. data/app/views/foreman_patch/plans/index.html.erb +32 -0
  157. data/app/views/foreman_patch/plans/new.html.erb +3 -0
  158. data/app/views/foreman_patch/plans/show.html.erb +19 -0
  159. data/app/views/foreman_patch/rounds/show.html.erb +54 -0
  160. data/app/views/foreman_patch/ticket_fields/_fields.html.erb +66 -0
  161. data/app/views/foreman_patch/ticket_fields/edit.html.erb +6 -0
  162. data/app/views/foreman_patch/ticket_fields/index.html.erb +26 -0
  163. data/app/views/foreman_patch/ticket_fields/new.html.erb +6 -0
  164. data/app/views/foreman_patch/window_plans/_form.html.erb +11 -0
  165. data/app/views/foreman_patch/window_plans/_hidden_layout.html.erb +7 -0
  166. data/app/views/foreman_patch/window_plans/edit.html.erb +3 -0
  167. data/app/views/foreman_patch/window_plans/new.html.erb +3 -0
  168. data/app/views/foreman_patch/windows/_form.html.erb +21 -0
  169. data/app/views/foreman_patch/windows/_groups.html.erb +2 -0
  170. data/app/views/foreman_patch/windows/_rounds.html.erb +24 -0
  171. data/app/views/foreman_patch/windows/_schedule.html.erb +16 -0
  172. data/app/views/foreman_patch/windows/_ticket.html.erb +12 -0
  173. data/app/views/foreman_patch/windows/edit.html.erb +3 -0
  174. data/app/views/foreman_patch/windows/new.html.erb +3 -0
  175. data/app/views/foreman_patch/windows/show.html.erb +27 -0
  176. data/app/views/foreman_patch/windows/show.json.erb +4 -0
  177. data/app/views/hosts/select_multiple_patch_group.html.erb +12 -0
  178. data/app/views/overrides/patch_groups/_host_patch_group_select.html.erb +9 -0
  179. data/app/views/templates/ensure_services.erb +28 -0
  180. data/config/api_routes.rb +37 -0
  181. data/config/initializers/pagelets.rb +6 -0
  182. data/config/initializers/safemode_jail.rb +4 -0
  183. data/config/routes/mount_engine.rb +3 -0
  184. data/config/routes/overrides.rb +10 -0
  185. data/config/routes.rb +47 -0
  186. data/db/migrate/20210202161304_create_foreman_patch_plans.rb +32 -0
  187. data/db/migrate/20210202163323_create_foreman_patch_cycles.rb +38 -0
  188. data/db/migrate/20210202164301_create_foreman_patch_groups.rb +37 -0
  189. data/db/migrate/20210226134103_add_name_to_cycles.rb +31 -0
  190. data/db/migrate/20210226162824_rename_default_window.rb +5 -0
  191. data/db/migrate/20210302165058_add_task_to_window_groups.rb +7 -0
  192. data/db/migrate/20210304141111_create_invocation.rb +16 -0
  193. data/db/migrate/20210519163923_add_cycle_end_date.rb +29 -0
  194. data/db/migrate/20210525154113_expand_window_groups.rb +27 -0
  195. data/db/migrate/20210723160142_add_cycle_plan_task_group.rb +7 -0
  196. data/db/migrate/20210831160044_cycle_plan_start_correction.rb +5 -0
  197. data/db/migrate/20210907104645_rename_group_priority.rb +5 -0
  198. data/db/migrate/20210909130118_remove_old_references.rb +14 -0
  199. data/db/migrate/20210910141428_rename_round.rb +7 -0
  200. data/db/migrate/20210910163542_rename_plan.rb +8 -0
  201. data/db/migrate/20211014212415_round_group_reference.rb +9 -0
  202. data/db/migrate/20220105224803_add_group_label.rb +25 -0
  203. data/db/migrate/20220114153808_plan_add_name_generator.rb +5 -0
  204. data/db/migrate/20220117103808_remove_cycle_description.rb +5 -0
  205. data/db/migrate/20220406110705_add_window_state.rb +37 -0
  206. data/db/migrate/20220407161120_add_round_status.rb +9 -0
  207. data/db/migrate/20220902134800_add_invocation_status.rb +28 -0
  208. data/db/seeds.d/100-assign_features_with_templates.rb +16 -0
  209. data/db/seeds.d/160-mail_notifications.rb +38 -0
  210. data/db/seeds.d/75-job_templates.rb +16 -0
  211. data/lib/foreman_patch/engine.rb +87 -0
  212. data/lib/foreman_patch/plugin.rb +47 -0
  213. data/lib/foreman_patch/version.rb +3 -0
  214. data/lib/foreman_patch.rb +4 -0
  215. data/lib/tasks/foreman_patch_tasks.rake +47 -0
  216. data/locale/Makefile +60 -0
  217. data/locale/en/foreman_patch.po +19 -0
  218. data/locale/foreman_patch.pot +19 -0
  219. data/locale/gemspec.rb +2 -0
  220. data/package.json +35 -0
  221. data/public/assets/foreman_patch/cycle_plans-e5667e178ba389908f5c815b24ec0ea77c340849d56bc39c5ce72bb626bd446a.scss +6 -0
  222. data/public/assets/foreman_patch/cycle_plans-e5667e178ba389908f5c815b24ec0ea77c340849d56bc39c5ce72bb626bd446a.scss.gz +0 -0
  223. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css +1 -0
  224. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css.gz +0 -0
  225. data/public/assets/foreman_patch/foreman_patch.json +1 -0
  226. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js +1 -0
  227. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js.gz +0 -0
  228. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css +1 -0
  229. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.css.gz +0 -0
  230. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js +6 -0
  231. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.gz +0 -0
  232. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map +1 -0
  233. data/public/webpack/foreman_patch/bundle-200e97f4e2ad9ed413ea.js.map.gz +0 -0
  234. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css +1 -0
  235. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.css.gz +0 -0
  236. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js +6 -0
  237. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.gz +0 -0
  238. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map +1 -0
  239. data/public/webpack/foreman_patch/foreman_patch-1e4f2d5e6f040a27aa7a.js.map.gz +0 -0
  240. data/public/webpack/foreman_patch/manifest.json +26 -0
  241. data/public/webpack/foreman_patch/manifest.json.gz +0 -0
  242. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js +2 -0
  243. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.gz +0 -0
  244. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map +1 -0
  245. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map.gz +0 -0
  246. data/test/factories/foreman_patch_factories.rb +5 -0
  247. data/test/test_plugin_helper.rb +6 -0
  248. data/test/unit/foreman_patch_test.rb +11 -0
  249. data/webpack/components/Cycle/Cycle.js +57 -0
  250. data/webpack/components/Cycle/CycleActions.js +21 -0
  251. data/webpack/components/Cycle/CycleConstants.js +2 -0
  252. data/webpack/components/Cycle/CycleHelpers.js +3 -0
  253. data/webpack/components/Cycle/CycleSelectors.js +10 -0
  254. data/webpack/components/Cycle/Window.js +32 -0
  255. data/webpack/components/Cycle/index.js +41 -0
  256. data/webpack/components/Groups/Group.js +20 -0
  257. data/webpack/components/Groups/Groups.js +46 -0
  258. data/webpack/components/Groups/GroupsHelpers.js +11 -0
  259. data/webpack/components/Groups/Priority.js +51 -0
  260. data/webpack/components/Invocation/Invocation.js +47 -0
  261. data/webpack/components/Invocation/InvocationActions.js +8 -0
  262. data/webpack/components/Invocation/InvocationConsts.js +1 -0
  263. data/webpack/components/Invocation/InvocationSelectors.js +14 -0
  264. data/webpack/components/Invocation/index.js +36 -0
  265. data/webpack/components/Invocations/Invocations.js +55 -0
  266. data/webpack/components/Invocations/InvocationsConstants.js +1 -0
  267. data/webpack/components/Invocations/InvocationsHelpers.js +11 -0
  268. data/webpack/components/Invocations/InvocationsPage.js +66 -0
  269. data/webpack/components/Invocations/InvocationsPage.scss +3 -0
  270. data/webpack/components/Invocations/InvocationsSelectors.js +21 -0
  271. data/webpack/components/Invocations/components/InvocationItem.js +66 -0
  272. data/webpack/components/Invocations/components/InvocationStatus.js +51 -0
  273. data/webpack/components/Invocations/index.js +99 -0
  274. data/webpack/components/Plan/Plan.js +90 -0
  275. data/webpack/components/Plan/PlanActions.js +12 -0
  276. data/webpack/components/Plan/PlanConstants.js +1 -0
  277. data/webpack/components/Plan/PlanSelectors.js +9 -0
  278. data/webpack/components/Plan/Window.js +33 -0
  279. data/webpack/components/Plan/index.js +36 -0
  280. data/webpack/components/PlanWindow/PlanWindow.js +55 -0
  281. data/webpack/components/PlanWindow/index.js +32 -0
  282. data/webpack/components/RoundProgress/AggregateStatus.js +58 -0
  283. data/webpack/components/RoundProgress/RoundProgress.js +48 -0
  284. data/webpack/components/RoundProgress/RoundProgressActions.js +9 -0
  285. data/webpack/components/RoundProgress/RoundProgressConstants.js +1 -0
  286. data/webpack/components/RoundProgress/RoundProgressSelectors.js +24 -0
  287. data/webpack/components/RoundProgress/index.js +44 -0
  288. data/webpack/components/Rounds/Rounds.js +57 -0
  289. data/webpack/components/Rounds/RoundsActions.js +8 -0
  290. data/webpack/components/Rounds/RoundsConsts.js +1 -0
  291. data/webpack/components/Rounds/RoundsSelectors.js +14 -0
  292. data/webpack/components/Rounds/components/RoundItem.js +52 -0
  293. data/webpack/components/Rounds/components/RoundStatus.js +40 -0
  294. data/webpack/components/Rounds/index.js +37 -0
  295. data/webpack/components/common/Calendar/Calendar.js +86 -0
  296. data/webpack/components/common/Calendar/Calendar.scss +76 -0
  297. data/webpack/components/common/Calendar/CalendarConstants.js +1 -0
  298. data/webpack/components/common/Calendar/CalendarHelpers.js +77 -0
  299. data/webpack/components/common/Calendar/Day/index.js +9 -0
  300. data/webpack/components/common/Calendar/Event.js +25 -0
  301. data/webpack/components/common/Calendar/Month/Day.js +51 -0
  302. data/webpack/components/common/Calendar/Month/Header.js +77 -0
  303. data/webpack/components/common/Calendar/Month/Month.js +47 -0
  304. data/webpack/components/common/Calendar/Month/index.js +1 -0
  305. data/webpack/components/common/Calendar/View.js +20 -0
  306. data/webpack/components/common/Calendar/Week/index.js +13 -0
  307. data/webpack/components/common/Calendar/index.js +2 -0
  308. data/webpack/components/common/Terminal/OutputLine.js +26 -0
  309. data/webpack/components/common/Terminal/Terminal.js +115 -0
  310. data/webpack/components/common/Terminal/Terminal.scss +47 -0
  311. data/webpack/index.js +20 -0
  312. metadata +438 -0
@@ -0,0 +1,110 @@
1
+ module ForemanPatch
2
+ class Plan < ::ApplicationRecord
3
+ include ForemanTasks::Concerns::ActionSubject
4
+
5
+ UNITS = ['days', 'weeks', 'months', 'years'].freeze
6
+ CORRECTIONS = ['weekday', 'last_day', 'last_weekday', 'avoid_weekend'].freeze
7
+
8
+ has_many :window_plans, class_name: 'ForemanPatch::WindowPlan', foreign_key: :plan_id, dependent: :delete_all, inverse_of: :plan
9
+
10
+ has_many :cycles, -> { order(start_date: :desc) }, class_name: 'ForemanPatch::Cycle', foreign_key: :plan_id, dependent: :nullify
11
+
12
+ belongs_to :task_group, class_name: 'ForemanPatch::PlanTaskGroup', inverse_of: :plan
13
+ has_many :tasks, through: :task_group, class_name: 'ForemanTasks::Task'
14
+
15
+ validates :name, presence: true, uniqueness: true
16
+ validates :units, inclusion: {in: UNITS}, allow_blank: false
17
+ validates :correction, inclusion: {in: CORRECTIONS}, allow_blank: true
18
+
19
+ scoped_search on: :name, complete_value: true
20
+ scoped_search on: :units, complete_value: true
21
+ scoped_search on: :interval, complete_value: true
22
+ scoped_search on: :start_date, complete_value: false
23
+
24
+ before_destroy :stop
25
+
26
+ def end_date
27
+ next_cycle_start - 1.day
28
+ end
29
+
30
+ def frequency
31
+ interval.send(units)
32
+ end
33
+
34
+ def stopped?
35
+ active_count == 0
36
+ end
37
+
38
+ def stop
39
+ self.active_count = 0
40
+ save!
41
+ tasks.active.each(&:cancel)
42
+ end
43
+
44
+ def next_cycle_start
45
+ next_date = start_date + frequency
46
+ next_date = send(correction, next_date) unless correction.blank?
47
+ next_date
48
+ end
49
+
50
+ def iterate
51
+ count = tasks.where(state: 'scheduled').count
52
+
53
+ if count < active_count or active_count == 0
54
+ ForemanTasks.async_task(Actions::ForemanPatch::Cycle::Create, self)
55
+ end
56
+ end
57
+
58
+ def to_params
59
+ {
60
+ name: ForemanPatch::CycleNameGenerator.generate(self),
61
+ start_date: start_date,
62
+ end_date: next_cycle_start - 1.day,
63
+ }
64
+ end
65
+
66
+ class Jail < Safemode::Jail
67
+ allow :start_date, :end_date, :frequency, :name, :interval, :units
68
+ end
69
+
70
+ private
71
+
72
+ def weekday(next_date)
73
+ offset = (next_date.day - 1) % 7
74
+ shift = start_date.wday - (next_date.wday - offset)
75
+ shift += 7 if shift < 0
76
+ next_date.advance(days: shift - offset)
77
+ end
78
+
79
+ def last_day(next_date)
80
+ next_date.end_of_month
81
+ end
82
+
83
+ def last_weekday(next_date)
84
+ next_date = next_date.end_of_month
85
+ ago = next_date.wday - start_date.wday
86
+ ago += 7 unless ago >= 0
87
+ next_date.advance(days: -ago)
88
+ end
89
+
90
+ def avoid_weekend(next_date)
91
+ if next_date.saturday?
92
+ (next_date.day == 1 ? next_date.advance(days: 2) : next_date.advance(days: -1))
93
+ elsif next_date.sunday?
94
+ (next_date.day == ::Time.days_in_month(next_date.month, next_date.year) ? next_date.advance(days: -2) : next_date.advance(days: 1))
95
+ else
96
+ next_date
97
+ end
98
+ end
99
+
100
+ def delay_options
101
+ Time.use_zone(Setting[:patch_schedule_time_zone]) do
102
+ {
103
+ start_at: start_date.beginning_of_day
104
+ }
105
+ end
106
+ end
107
+
108
+ end
109
+ end
110
+
@@ -0,0 +1,11 @@
1
+ module ForemanPatch
2
+ class PlanTaskGroup < ::ForemanTasks::TaskGroup
3
+ has_one :plan, foreign_key: :task_group_id, dependent: :nullify, inverse_of: :task_group, class_name: 'ForemanPatch::Plan'
4
+
5
+ alias_method :resource, :plan
6
+
7
+ def resource_name
8
+ N_('Plan')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+ module ForemanPatch
2
+ class Round < ::ApplicationRecord
3
+ include ForemanTasks::Concerns::ActionSubject
4
+
5
+ belongs_to :window, class_name: 'ForemanPatch::Window'
6
+ has_one :cycle, class_name: 'ForemanPatch::Cycle', through: :window
7
+ belongs_to :group, class_name: 'ForemanPatch::Group'
8
+
9
+ belongs_to :task, class_name: 'ForemanTasks::Task'
10
+ has_many :sub_tasks, through: :task
11
+
12
+ validates :window, presence: true
13
+
14
+ has_many :invocations, class_name: 'ForemanPatch::Invocation', foreign_key: :round_id, inverse_of: :round, dependent: :destroy
15
+ has_many :hosts, through: :invocations
16
+
17
+ scope :planned, -> { where(status: 'planned') }
18
+ scope :pending, -> { where(status: 'pending') }
19
+ scope :running, -> { where(status: 'running') }
20
+ scope :complete, -> { where(status: 'complete') }
21
+
22
+ scope :in_windows, -> (*args) { where(window: args.flatten) }
23
+ scope :missing_hosts, -> (*args) do
24
+ left_joins(:invocations, { group: :group_facets }).scoping do
25
+ where(foreman_patch_group_facets: { host_id: args.flatten },
26
+ foreman_patch_invocations: { host_id: nil })
27
+ end
28
+ end
29
+
30
+ scoped_search on: :name, complete_value: true
31
+ scoped_search on: :status, complete_value: true
32
+
33
+ def progress(total = nil, done = nil)
34
+ if invocations.empty? || done == 0
35
+ 0
36
+ else
37
+ total ||= invocations.count
38
+ done ||= sub_tasks.where(result: %w(success warning error)).count
39
+ ((done.to_f / total) * 100).round
40
+ end
41
+ end
42
+
43
+ def progress_report
44
+ invocations.reduce({
45
+ pending: 0,
46
+ running: 0,
47
+ success: 0,
48
+ warning: 0,
49
+ failed: 0,
50
+ cancelled: 0,
51
+ }) do |report, invocation|
52
+ status = (invocation.status == 'planned' ? 'pending' : invocation.status)
53
+ report[status.to_sym] += 1
54
+ report
55
+ end
56
+ end
57
+
58
+ def finished?
59
+ !(task.nil? || task.pending?)
60
+ end
61
+
62
+ class Jail < ::Safemode::Jail
63
+ allow :id, :name, :description, :invocations, :hosts, :priority, :max_unavailable, :status
64
+ end
65
+
66
+ end
67
+ end
68
+
@@ -0,0 +1,23 @@
1
+ module ForemanPatch
2
+ class TicketField < LookupKey
3
+
4
+ def ticket?
5
+ true
6
+ end
7
+
8
+ def self.humanized_class_name(options = nil)
9
+ end
10
+
11
+ def path
12
+ path = self[:path]
13
+ path.presence || array2path(['name', 'cycle'])
14
+ end
15
+
16
+ def path=(value)
17
+ return unless value
18
+ using_default = value.tr("\r", "") == array2path(['name', 'cycle'])
19
+ self[:path] = using_default ? nil : value
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,123 @@
1
+ module ForemanPatch
2
+ class Window < ::ApplicationRecord
3
+ include ForemanTasks::Concerns::ActionSubject
4
+
5
+ belongs_to :cycle, class_name: 'ForemanPatch::Cycle', inverse_of: :windows
6
+
7
+ belongs_to :task, class_name: 'ForemanTasks::Task'
8
+ has_many :sub_tasks, through: :task
9
+
10
+ has_many :rounds, -> { order(priority: :asc) }, class_name: 'ForemanPatch::Round', inverse_of: :window, dependent: :destroy
11
+ has_many :groups, through: :rounds
12
+ has_many :invocations, through: :rounds
13
+ has_many :hosts, through: :rounds
14
+
15
+ validates :cycle, presence: true
16
+ validates :name, presence: true
17
+ validates :start_at, presence: true
18
+ validates :end_by, presence: true
19
+
20
+ scope :planned, -> { where(status: 'planned') }
21
+ scope :scheduled, -> { where(status: 'scheduled') }
22
+ scope :running, -> { where(status: 'running') }
23
+ scope :completed, -> { where(status: 'completed') }
24
+
25
+ scope :with_status, -> (*args) { where(status: args.flatten) }
26
+ scope :with_hosts, -> (*args) do
27
+ left_joins(rounds: [:invocations, {group: :group_facets}]).scoping do
28
+ where(foreman_patch_group_facets: { host_id: args.flatten })
29
+ .or(where(foreman_patch_invocations: { host_id: args.flatten }))
30
+ end
31
+ end
32
+
33
+ scoped_search on: :name, complete_value: true
34
+ scoped_search on: :start_at, complete_value: false
35
+ scoped_search on: :end_by, complete_value: false
36
+ scoped_search on: :cycle_id, complete_value: false
37
+ scoped_search on: :status, complete_value: true
38
+ scoped_search relation: :cycle, on: :name, complete_value: true, rename: 'cycle', only_explicit: true
39
+
40
+ after_update :reschedule, if: :needs_reschedule?
41
+ after_update :republish, if: :needs_republish?
42
+
43
+ def ticket
44
+ @ticket ||= Ticket.get(self)
45
+ end
46
+
47
+ def duration
48
+ end_by - start_at
49
+ end
50
+
51
+ def duration=(duration)
52
+ self.end_by = start_at + duration
53
+ end
54
+
55
+ def move_to(time)
56
+ span = duration
57
+ self.start_at = time
58
+ self.end_by = time + span
59
+ end
60
+
61
+ def move_by(duration)
62
+ self.start_at = self.start_at + duration
63
+ self.end_by = self.end_by + duration
64
+ end
65
+
66
+ class Jail < ::Safemode::Jail
67
+ allow :id, :name, :description, :cycle, :start_at, :end_by, :rounds
68
+ end
69
+
70
+ def scheduled?
71
+ (not task.blank?) and task.scheduled?
72
+ end
73
+
74
+ def schedule
75
+ User.as_anonymous_admin do
76
+ ::ForemanTasks.delay(::Actions::ForemanPatch::Window::Patch, delay_options, self) unless scheduled?
77
+ end
78
+ end
79
+
80
+ def cancel(force = false)
81
+ method = force ? :abort : :cancel
82
+ task.send(method) unless task.blank?
83
+ end
84
+
85
+ def published?
86
+ not ticket_id.blank?
87
+ end
88
+
89
+ private
90
+
91
+ def needs_reschedule?
92
+ scheduled? and (saved_changes.keys & ['start_at', 'end_by']).any?
93
+ end
94
+
95
+ def reschedule
96
+ User.as_anonymous_admin do
97
+ task.cancel
98
+ task.destroy
99
+
100
+ ::ForemanTasks.delay(::Actions::ForemanPatch::Window::Patch, delay_options, self)
101
+ end
102
+ end
103
+
104
+ def needs_republish?
105
+ published? and (saved_changes.keys - ['ticket_id', 'updated_at']).any?
106
+ end
107
+
108
+ def republish
109
+ User.as_anonymous_admin do
110
+ ::ForemanTasks.async_task(::Actions::ForemanPatch::Window::Publish, self)
111
+ end
112
+ end
113
+
114
+ def delay_options
115
+ {
116
+ start_at: start_at,
117
+ start_before: end_by,
118
+ }
119
+ end
120
+
121
+ end
122
+ end
123
+
@@ -0,0 +1,77 @@
1
+ module ForemanPatch
2
+ class WindowPlan < ::ApplicationRecord
3
+ include ForemanTasks::Concerns::ActionSubject
4
+
5
+ attr_accessor :start_at, :end_by
6
+
7
+ self.skip_time_zone_conversion_for_attributes = [:start_time]
8
+
9
+ belongs_to :plan, class_name: 'ForemanPatch::Plan', inverse_of: :window_plans
10
+
11
+ has_many :groups, class_name: 'ForemanPatch::Group', foreign_key: :default_window_plan_id
12
+
13
+ validates :name, presence: true, uniqueness: { scope: :plan_id }
14
+ validates :start_day, presence: true
15
+ validates :start_time, presence: true
16
+ validates :duration, presence: true
17
+
18
+ scoped_search on: :name, complete_value: true
19
+ scoped_search on: :plan_id, complete_value: true
20
+ scoped_search on: :start_day, complete_value: true
21
+ scoped_search on: :start_time, complete_value: true
22
+
23
+ scoped_search relation: :plan, on: :name, complete_value: true
24
+
25
+ after_initialize :init
26
+
27
+ def start_time
28
+ value = read_attribute(:start_time)
29
+ return nil if value.blank?
30
+
31
+ if value.acts_like?(:time)
32
+ args = [value.year, value.month, value.day, value.hour, value.min, value.sec]
33
+ time = Time.find_zone(Setting[:patch_schedule_time_zone]).local(*args)
34
+ else
35
+ time = Time.find_zone(Setting[:patch_schedule_time_zone]).parse(value)
36
+ end
37
+ time.to_time
38
+ end
39
+
40
+ def start_time=(value)
41
+ if value.acts_like?(:time)
42
+ time = value.in_time_zone(Setting[:patch_schedule_time_zone]).time
43
+ else
44
+ time = Time.find_zone(Setting[:patch_schedule_time_zone]).parse(value).time
45
+ end
46
+ write_attribute(:start_time, time)
47
+ end
48
+
49
+ def start_at
50
+ start_date = plan.start_date + start_day.days
51
+ start_time.change(year: start_date.year, month: start_date.month, day: start_date.day)
52
+ end
53
+
54
+ def end_by
55
+ start_at + duration
56
+ end
57
+
58
+ def to_params
59
+ {
60
+ name: name,
61
+ description: description,
62
+ start_at: start_at,
63
+ end_by: end_by,
64
+ }
65
+ end
66
+
67
+ private
68
+
69
+ def init
70
+ self.start_day ||= 0
71
+ self.start_time ||= Time.find_zone(Setting[:patch_schedule_time_zone]).parse('00:00:00')
72
+ self.duration ||= 1.hour.to_i
73
+ end
74
+
75
+ end
76
+ end
77
+
@@ -0,0 +1,11 @@
1
+ module ForemanPatch
2
+ class WindowTaskGroup < ::ForemanTasks::TaskGroup
3
+ has_one :window, foreign_key: :task_group_id, dependent: :nullify, class_name: 'ForemanPatch::Window'
4
+
5
+ alias_method :resource, :window
6
+
7
+ def resource_name
8
+ N_('Window')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ class Setting::Patching < ::Setting
2
+ def self.default_settings
3
+ http_proxy_select = [{
4
+ name: _('Http Proxies'),
5
+ class: 'HttpProxy',
6
+ scope: 'all',
7
+ value_method: 'name',
8
+ text_method: 'name_and_url',
9
+ }]
10
+
11
+ time_zone_select = [{
12
+ name: _('Time Zones'),
13
+ class: 'ActiveSupport::TimeZone',
14
+ scope: 'all',
15
+ value_method: 'name',
16
+ text_method: 'name',
17
+ }]
18
+
19
+ # set(name, description, default, fullname, value, { options })
20
+ [
21
+ self.set('host_max_wait_for_up', N_("Maximum seconds to wait for a host after patching restart."),
22
+ 600, N_("Max wait for host up")),
23
+ self.set('host_patch_timeout', N_("Maximum seconds for a patching invocation to run before timing out"),
24
+ nil, N_('Patch Timeout')),
25
+ self.set('patch_schedule_time_zone', N_('Time zone used to base patch window scheduling off of.'),
26
+ 'UTC', N_('Patch Schedule Time Zone'), nil,
27
+ collection: proc { time_zone_select }),
28
+ self.set('ticket_api_host', N_('Host used for change management tickets'),
29
+ nil, N_('Ticket API host')),
30
+ self.set('ticket_api_proxy', N_('HTTP Proxy to access ticket API host'),
31
+ nil, N_('Ticket API HTTP proxy'), nil,
32
+ collection: proc { http_proxy_select }, include_blank: N_('no proxy')),
33
+ self.set('ticket_api_user', N_('User with access to ticket API'),
34
+ nil, N_('Ticket API user')),
35
+ self.set('ticket_api_password', N_('Password for ticket API user'),
36
+ nil, N_('Ticket API password'), nil, { encrypted: true }),
37
+ self.set('ticket_api_path', N_('Ticket API path for REST/CRUD operations'),
38
+ '/api/now/table/change_request', N_('Ticket API path')),
39
+ self.set('ticket_web_ui_path', N_('Path for opening a ticket in the web UI'),
40
+ '/change_request.do?sys_id=:id', N_('Ticket Web UI path')),
41
+ self.set('ticket_label_field', N_('Name of the field used for the ticket label'),
42
+ 'number', N_('Ticket label field')),
43
+ self.set('ticket_id_field', N_('Name of the field used for the ticket id'),
44
+ 'sys_id', N_('Ticket ID field')),
45
+ self.set('skip_broken_patches', N_('Skip broken dependencies during patching'), true, N_('Skip broken patches'))
46
+ ]
47
+ end
48
+
49
+ def self.humanized_category
50
+ N_('Patching')
51
+ end
52
+
53
+ def self.load_defaults
54
+ BLANK_ATTRS.concat %w(ticket_api_host ticket_api_proxy ticket_api_user ticket_api_password, host_patch_timeout)
55
+ super
56
+ end
57
+ end
@@ -0,0 +1,38 @@
1
+ module ForemanPatch
2
+ class CycleNameGenerator
3
+ REGEX = /%([-_0^#:]*)(\d*)([q])/.freeze
4
+
5
+ def self.generate(plan)
6
+ return plan.name if plan.cycle_name.blank?
7
+
8
+ generator = new(plan.cycle_name, plan.start_date)
9
+ generator.render
10
+ end
11
+
12
+ def self.rename(cycle)
13
+ return if cycle.plan.blank?
14
+ return if cycle.plan.cycle_name.blank?
15
+
16
+ generator = new(cycle.plan.cycle_name, cycle.start_date)
17
+ cycle.update(name: generator.render)
18
+ end
19
+
20
+ attr_accessor :format, :date
21
+
22
+ def initialize(format, date)
23
+ @format = format
24
+ @date = date
25
+ end
26
+
27
+ def render
28
+ date.strftime(format.gsub(REGEX, quarter(date)))
29
+ end
30
+
31
+ private
32
+
33
+ def quarter(date)
34
+ (date.month / 3.0).ceil.to_s
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,110 @@
1
+ module ForemanPatch
2
+ module Ticket
3
+ class AffectedItems
4
+ include API
5
+
6
+ attr_reader :ticket
7
+
8
+ def initialize(ticket)
9
+ @ticket = ticket
10
+ end
11
+
12
+ def items
13
+ @items ||= get_affected_items
14
+ end
15
+
16
+ def set(hosts)
17
+ cmdb_items = get_configuration_items(hosts)
18
+
19
+ add_affected_items(select_cmdb_items(cmdb_items, true))
20
+
21
+ remove_affected_items(select_affected_items(cmdb_items, true))
22
+
23
+ @items = get_affected_items
24
+ end
25
+
26
+ def add(hosts)
27
+ add_affected_items(select_cmdb_items(get_configuration_items(hosts), true))
28
+
29
+ @items = get_affected_items
30
+ end
31
+
32
+ def remove(hosts)
33
+ remove_affected_items(select_affected_items(get_configuration_items(hosts)))
34
+
35
+ @items = get_affected_items
36
+ end
37
+
38
+ private
39
+
40
+ def get_configuration_items(hosts)
41
+ params = {
42
+ sysparm_query: "host_nameIN#{hosts.map(&:name).join(',')}",
43
+ sysparm_exclude_reference_link: true,
44
+ sysparm_fields: 'sys_id,host_name',
45
+ }
46
+
47
+ get('/api/now/table/cmdb_ci_server', params)
48
+
49
+ response.nil? ? [] : response['result']
50
+ end
51
+
52
+ def get_affected_items
53
+ params = {
54
+ sysparm_query: "task=#{ticket.id}",
55
+ sysparm_exclude_reference_link: true,
56
+ sysparm_fields: 'sys_id,task,ci_item',
57
+ }
58
+
59
+ get('/api/now/table/task_ci', params)
60
+
61
+ response.nil? ? [] : response['result']
62
+ end
63
+
64
+ def select_cmdb_items(cmdb_items, inverse = false)
65
+ affected_item_ids = get_affected_items.map { |i| i['cm_item'] }
66
+ cmdb_items.select do |cmdb_item|
67
+ inverse ^ (affected_item_ids.include? cmdb_item['sys_id'])
68
+ end
69
+ end
70
+
71
+ def select_affected_items(cmdb_items, inverse = false)
72
+ cmdb_item_ids = cmdb_items.map { |i| i['sys_id'] }
73
+ items.select do |affected_item|
74
+ inverse ^ (cmdb_item_ids.include? affected_item['ci_item'])
75
+ end
76
+ end
77
+
78
+ def add_affected_items(cmdb_items)
79
+ cmdb_items.each do |ci_item|
80
+ add_affected_item(ci_item)
81
+ end
82
+ end
83
+
84
+ def add_affected_item(cmdb_ci)
85
+ params = {
86
+ sysparm_exclude_reference_link: true,
87
+ sysparm_fields: 'sys_id,task,ci_item',
88
+ }
89
+
90
+ payload = {
91
+ ci_item: cmdb_ci['sys_id'],
92
+ task: ticket.id,
93
+ }
94
+
95
+ post('/api/now/table/task_ci', payload, params)
96
+ end
97
+
98
+ def remove_affected_items(affected_items)
99
+ affected_items.each do |affected_item|
100
+ remove_affected_item(affected_item)
101
+ end
102
+ end
103
+
104
+ def remove_affected_item(affected_item)
105
+ delete("/api/now/table/task_ci/#{affected_item['sys_id']}")
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,68 @@
1
+ module ForemanPatch
2
+ module Ticket
3
+ module API
4
+ attr_reader :response, :errors
5
+
6
+ private
7
+
8
+ def host
9
+ Setting[:ticket_api_host]
10
+ end
11
+
12
+ def url(path)
13
+ host + path
14
+ end
15
+
16
+ def proxy
17
+ return nil if Setting[:ticket_api_proxy].blank?
18
+
19
+ HttpProxy.friendly.find(Setting[:ticket_api_proxy])&.url
20
+ end
21
+
22
+ def get(path, params = {})
23
+ request(:get, path, params)
24
+ end
25
+
26
+ def post(path, payload, params = {})
27
+ request(:post, path, params, payload)
28
+ end
29
+
30
+ def put(path, payload, params = {})
31
+ request(:put, path, params, payload)
32
+ end
33
+
34
+ def delete(path)
35
+ request(:delete, path)
36
+ end
37
+
38
+ def request(method, path, params = {}, payload = nil)
39
+ @response = nil
40
+
41
+ args = {
42
+ method: method,
43
+ url: url(path),
44
+ headers: {
45
+ accept: :json,
46
+ content_type: :json,
47
+ params: params,
48
+ },
49
+ user: Setting[:ticket_api_user],
50
+ password: Setting[:ticket_api_password],
51
+ }
52
+
53
+ args[:payload] = payload.to_json unless payload.nil?
54
+ args[:proxy] = proxy
55
+
56
+ raw = RestClient::Request.execute(args)
57
+
58
+ @response = JSON.parse(raw)
59
+ rescue RestClient::ExceptionWithResponse => error
60
+ @errors = JSON.parse(error.response)
61
+ Rails.logger.error(error)
62
+ rescue => error
63
+ Rails.logger.error(error)
64
+ end
65
+
66
+ end
67
+ end
68
+ end