foreman_patch 1.1.1

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 (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