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,47 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class EnsureServices < Actions::EntryAction
5
+ include Actions::Helpers::WithFeatureAction
6
+
7
+ def resource_locks
8
+ :link
9
+ end
10
+
11
+ def plan(host)
12
+ action_subject(host)
13
+
14
+ sequence do
15
+ plan_feature_action('ensure_services', host)
16
+ plan_self
17
+ end
18
+ end
19
+
20
+ def run
21
+ if exit_status != 0
22
+ users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
23
+
24
+ begin
25
+ MailNotification[:patch_invocation_failure].deliver(users: users, host: host, output: live_output) unless users.blank?
26
+ rescue => error
27
+ message = _('Unable to send patch invocation failure: %{error}') % {error: error}
28
+ Rails.logger.error(message)
29
+ end
30
+
31
+ fail _('Ensure services failed')
32
+ end
33
+ end
34
+
35
+ def rescue_strategy
36
+ ::Dynflow::Action::Rescue::Skip
37
+ end
38
+
39
+ def host
40
+ @host ||= ::Host.find(input[:host][:id])
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,93 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class Patch < Actions::EntryAction
5
+ include ::Actions::Helpers::WithContinuousOutput
6
+
7
+ execution_plan_hooks.use :update_status, on: ::Dynflow::ExecutionPlan.states
8
+
9
+ def plan(invocation)
10
+ action_subject(invocation.host, invocation_id: invocation.id)
11
+
12
+ invocation.update!(task_id: task.id)
13
+
14
+ sequence do
15
+ plan_action(Actions::ForemanPatch::Invocation::Action, host, 'katello_package_update',
16
+ pre_script: 'yum clean all; subscription-manager refresh',
17
+ package: Setting[:skip_broken_patches] ? '--skip-broken' : nil)
18
+ plan_action(Actions::ForemanPatch::Invocation::Action, host, 'power_action',
19
+ action: 'restart')
20
+ plan_action(Actions::ForemanPatch::Invocation::WaitForHost, host)
21
+ plan_action(Actions::ForemanPatch::Invocation::Action, host, 'ensure_services', false)
22
+ plan_self
23
+ end
24
+ end
25
+
26
+ def finalize
27
+ host.group_facet.last_patched_at = Time.current
28
+ host.group_facet.save!
29
+ end
30
+
31
+ def update_status(execution_plan)
32
+ return unless root_action?
33
+
34
+ case execution_plan.state
35
+ when 'scheduled', 'pending', 'planning', 'planned'
36
+ invocation.update!(status: 'pending')
37
+ when 'running'
38
+ invocation.update!(status: 'running')
39
+ else
40
+ action = failed_action
41
+ if action.nil?
42
+ invocation.update!(status: 'success')
43
+ else
44
+ invocation.update!(status: action.required? ? 'error' : 'warning')
45
+ end
46
+ end
47
+ end
48
+
49
+ def live_output
50
+ continuous_output.sort!
51
+ continuous_output.raw_outputs
52
+ end
53
+
54
+ def continuous_output_providers
55
+ planned_actions.select do |action|
56
+ action.respond_to?(:fill_continuous_output)
57
+ end
58
+ end
59
+
60
+ def rescue_strategy
61
+ planned_actions.each do |planned_action|
62
+ if planned_action.steps.compact.any? { |step| step.state == :error }
63
+ return rescue_strategy_for_planned_action(planned_action)
64
+ end
65
+ end
66
+ rescue_strategy_for_self
67
+ end
68
+
69
+ def rescue_strategy_for_self
70
+ ::Dynflow::Action::Rescue::Fail
71
+ end
72
+
73
+ private
74
+
75
+ def host
76
+ @host ||= ::Host.find(input[:host][:id])
77
+ end
78
+
79
+ def invocation
80
+ @invocation ||= ::ForemanPatch::Invocation.find(input[:invocation_id])
81
+ end
82
+
83
+ def failed_action
84
+ planned_actions.find do |action|
85
+ action.steps.compact.any? { |step| [:error, :skipped].include? step.state }
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
93
+
@@ -0,0 +1,21 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class Reschedule < Actions::EntryAction
5
+
6
+ def plan(invocation)
7
+ action_subject(invocation)
8
+
9
+ round = invocation.cycle.rounds.find_by(group: invocation.host.group)
10
+
11
+ if round.nil?
12
+ invocation.destroy
13
+ else
14
+ invocation.update!(round: round)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,101 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class Restart < Actions::EntryAction
5
+ include Actions::Helpers::WithFeatureAction
6
+ include Dynflow::Action::Polling
7
+
8
+ def plan(host)
9
+ action_subject(host)
10
+
11
+ sequence do
12
+ plan_feature_action('power_action', host, action: 'restart')
13
+ plan_self
14
+ end
15
+ end
16
+
17
+ def done?
18
+ external_task[:status] == :running
19
+ end
20
+
21
+ def invoke_external_task
22
+ if exit_status != 0
23
+ send_failure_notification
24
+ fail(_('Restart command failed to execute'))
25
+ end
26
+
27
+ schedule_timeout(Setting[:host_max_wait_for_up]) if Setting[:host_max_wait_for_up]
28
+
29
+ { status: :stopping }
30
+ end
31
+
32
+ def poll_external_task
33
+ socket = TCPSocket.new(host.ip, Setting[:remote_execution_ssh_port])
34
+ socket.close
35
+
36
+ if external_task[:status] == :stopping
37
+ log_poll_result(_('Server status: stopping'))
38
+ { status: :stopping }
39
+ else
40
+ log_poll_result(_('Server status: running'))
41
+ { status: :running }
42
+ end
43
+ rescue
44
+ log_poll_result(_('Server status: starting'))
45
+
46
+ { status: :starting }
47
+ end
48
+
49
+ def poll_intervals
50
+ case external_task[:status]
51
+ when :stopping
52
+ [1]
53
+ when :starting
54
+ [10]
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def process_timeout
61
+ continuous_output.add_output(_('Server did not respond within alloted time after restart.'))
62
+
63
+ send_failure_notification
64
+
65
+ fail("Timeout exceeded.")
66
+ end
67
+
68
+ def log_poll_result(status)
69
+ results = delegated_output.fetch('result', [])
70
+
71
+ results << {
72
+ 'output_type' => 'debug',
73
+ 'output' => status,
74
+ 'timestamp' => Time.now.getlocal
75
+ }
76
+ end
77
+
78
+ def send_failure_notification
79
+ users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
80
+
81
+ begin
82
+ MailNotification[:patch_invocation_failure].deliver(user: users, host: host, output: live_output) unless users.blank?
83
+ rescue => error
84
+ message = _('Unable to send patch invocation failure: %{error}') % {error: error}
85
+ Rails.logger.error(message)
86
+ end
87
+ end
88
+
89
+ def rescue_strategy
90
+ ::Dynflow::Action::Rescue::Fail
91
+ end
92
+
93
+ def host
94
+ @host ||= ::Host.find(input[:host][:id])
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end
101
+
@@ -0,0 +1,52 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class UpdatePackages < Actions::EntryAction
5
+ include Actions::Helpers::WithFeatureAction
6
+
7
+ def resource_locks
8
+ :link
9
+ end
10
+
11
+ def plan(host)
12
+ action_subject(host)
13
+
14
+ sequence do
15
+ plan_feature_action('katello_package_update', host,
16
+ pre_script: 'yum clean all; subscription-manager refresh',
17
+ package: Setting[:skip_broken_patches] ? '--skip-broken' : nil)
18
+ plan_self
19
+ end
20
+ end
21
+
22
+ def run
23
+ if exit_status != 0
24
+ users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
25
+
26
+ begin
27
+ MailNotification[:patch_invocation_failure].deliver(users: users, host: host, output: live_output) unless users.blank?
28
+ rescue => error
29
+ message = _('Unable to send patch invocation failure: %{error}') % {error: error}
30
+ Rails.logger.error(message)
31
+ end
32
+
33
+ fail _('Package update failed')
34
+ else
35
+ host.group_facet.last_patched_at = Time.current
36
+ host.group_facet.save!
37
+ end
38
+ end
39
+
40
+ def rescue_strategy
41
+ ::Dynflow::Action::Rescue::Fail
42
+ end
43
+
44
+ def host
45
+ @host ||= ::Host.find(input[:host][:id])
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,103 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class WaitForHost < Actions::EntryAction
5
+ include Actions::Helpers::WithContinuousOutput
6
+ include Actions::Helpers::FailureNotification
7
+ include Dynflow::Action::Polling
8
+
9
+ def plan(host)
10
+ action_subject(host)
11
+
12
+ plan_self
13
+ end
14
+
15
+ def done?
16
+ external_task[:status] == 'available'
17
+ end
18
+
19
+ def invoke_external_task
20
+ schedule_timeout(Setting[:host_max_wait_for_up]) if Setting[:host_max_wait_for_up]
21
+
22
+ { status: 'waiting' }
23
+ end
24
+
25
+ def poll_external_task
26
+ socket = TCPSocket.new(host.ip, Setting[:remote_execution_ssh_port])
27
+
28
+ status = starting? ? 'available' : 'waiting'
29
+
30
+ { status: status }
31
+ rescue
32
+ status = 'starting'
33
+
34
+ { status: status }
35
+ ensure
36
+ socket.close if socket
37
+ add_output("Poll result: #{status}")
38
+ end
39
+
40
+ def poll_intervals
41
+ case external_task[:status]
42
+ when 'waiting'
43
+ [10, 1]
44
+ when 'starting'
45
+ [10]
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def on_finish
52
+ add_output(_('Host is up'), 'stdout')
53
+ end
54
+
55
+ def process_timeout
56
+ add_output(_('Server did not respond withing alloted time after restart.'), 'stderr')
57
+ send_failure_notification
58
+ fail('Timeout exceeded.')
59
+ end
60
+
61
+ def rescue_strategy
62
+ ::Dynflow::Action::Rescue::Fail
63
+ end
64
+
65
+ def live_output
66
+ continuous_output.sort!
67
+ continuous_output.raw_outputs
68
+ end
69
+
70
+ def continuous_output_providers
71
+ super << self
72
+ end
73
+
74
+ def fill_continuous_output(continuous_output)
75
+ output.fetch('result', []).each do |raw_output|
76
+ continuous_output.add_raw_output(raw_output)
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def host
83
+ @host ||= ::Host.find(input[:host][:id])
84
+ end
85
+
86
+ def starting?
87
+ external_task[:status] == 'starting'
88
+ end
89
+
90
+ def add_output(message, type = 'debug', timestamp = Time.now.getlocal)
91
+ formatted_output = {
92
+ output_type: type,
93
+ output: message,
94
+ timestamp: timestamp.to_f
95
+ }
96
+
97
+ output[:result] = [] if output[:result].nil?
98
+ output[:result] << formatted_output
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,21 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Round
4
+ class AddMissingHosts < Actions::EntryAction
5
+
6
+ def plan(round, *hosts)
7
+ hosts = hosts.flatten
8
+ action_subject(round, hosts: hosts.map(&:to_action_input))
9
+
10
+ # Don't add already run hosts
11
+ hosts -= round.cycle.hosts
12
+
13
+ round.group.hosts.where(id: hosts).each do |host|
14
+ round.invocations.find_or_create_by!(host_id: host.id)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Round
4
+ class Create < Actions::EntryAction
5
+
6
+ def resource_locks
7
+ :link
8
+ end
9
+
10
+ def plan(group, window)
11
+ action_subject(group, window)
12
+
13
+ round = window.rounds.create!({
14
+ group: group,
15
+ name: group.name,
16
+ description: group.description,
17
+ priority: group.priority,
18
+ max_unavailable: group.max_unavailable,
19
+ })
20
+
21
+ plan_self(round: round.to_action_input)
22
+ plan_action(Actions::ForemanPatch::Round::ResolveHosts, round)
23
+ end
24
+
25
+ def run
26
+ output[:round] = round.to_action_input
27
+ end
28
+
29
+ def round
30
+ @round = ::ForemanPatch::Round.find(input[:round][:id])
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,81 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Round
4
+ class Patch < Actions::ActionWithSubPlans
5
+ include Dynflow::Action::WithBulkSubPlans
6
+
7
+ def plan(round)
8
+ action_subject(round)
9
+
10
+ limit_concurrency_level round.max_unavailable unless round.max_unavailable.nil?
11
+
12
+ plan_self
13
+
14
+ round.update!(status: 'pending')
15
+ end
16
+
17
+ def create_sub_plans
18
+ current_batch.map do |invocation|
19
+ trigger(Actions::ForemanPatch::Invocation::Patch, invocation)
20
+ end
21
+ end
22
+
23
+ def rescue_strategy
24
+ ::Dynflow::Action::Rescue::Skip
25
+ end
26
+
27
+ def run(event = nil)
28
+ super unless event == Dynflow::Action::Skip
29
+ end
30
+
31
+ def initiate
32
+ round.update!(status: 'running')
33
+
34
+ users = ::User.select { |user| user.receives?(:patch_group_initiated) }.compact
35
+
36
+ begin
37
+ MailNotification[:patch_group_initiated].deliver(users: users, group: round) unless users.blank?
38
+ rescue => error
39
+ Rails.logger.error(error)
40
+ end
41
+
42
+ super
43
+ end
44
+
45
+ def check_for_errors!
46
+ end
47
+
48
+ def on_finish
49
+ round.update!(status: 'complete')
50
+
51
+ users = ::User.select { |user| user.receives?(:patch_group_completed) }.compact
52
+
53
+ MailNotification[:patch_group_completed].deliver(users: users, group: round) unless users.blank?
54
+ rescue => error
55
+ Rails.logger.error(error)
56
+ end
57
+
58
+ def round
59
+ @round ||= ::ForemanPatch::Round.find(input[:round][:id])
60
+ end
61
+
62
+ def invocations
63
+ round.invocations.order(:id)
64
+ end
65
+
66
+ def batch(from, size)
67
+ invocations.offset(from).limit(size)
68
+ end
69
+
70
+ def total_count
71
+ output[:total_count] || invocations.count
72
+ end
73
+
74
+ def humanized_name
75
+ 'Patch Group: %s' % round.name
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,33 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Round
4
+ class Plan < Actions::EntryAction
5
+
6
+ def resource_locks
7
+ :link
8
+ end
9
+
10
+ def plan(group, window)
11
+ action_subject(group, window: window)
12
+
13
+ action = plan_action(::Actions::ForemanPatch::Round::Create, params(group, window))
14
+ plan_action(::Actions::ForemanPatch::Round::ResolveHosts, action.output[:round])
15
+ end
16
+
17
+ private
18
+
19
+ def params(group, window)
20
+ {
21
+ window: window,
22
+ group: group.to_action_input,
23
+ name: group.name,
24
+ description: group.description,
25
+ priority: group.priority,
26
+ max_unavailable: group.max_unavailable,
27
+ }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Round
4
+ class ResolveHosts < Actions::EntryAction
5
+
6
+ def plan(round)
7
+ input.update serialize_args(round: round)
8
+ plan_self
9
+ end
10
+
11
+ def run
12
+ output[:invocations] = {
13
+ added: add_missing_hosts,
14
+ removed: remove_non_group_hosts,
15
+ }
16
+ end
17
+
18
+ private
19
+
20
+ def add_missing_hosts
21
+ return [] if round.group.nil?
22
+
23
+ round.group.hosts.map do |host|
24
+ round.invocations.find_or_create_by!(host_id: host.id).to_action_input
25
+ end
26
+ end
27
+
28
+ def remove_non_group_hosts
29
+ return [] if round.group.nil?
30
+
31
+ invocations = round.invocations.where.not(host_id: round.group.host_ids).destroy_all
32
+
33
+ invocations.map do |invocation|
34
+ invocation.to_action_input
35
+ end
36
+ end
37
+
38
+ def round
39
+ @round ||= ::ForemanPatch::Round.find(input[:round][:id])
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Window
4
+ class Create < Actions::EntryAction
5
+
6
+ def resource_locks
7
+ :link
8
+ end
9
+
10
+ def plan(window_plan, cycle)
11
+ action_subject(window_plan, cycle)
12
+
13
+ window = cycle.windows.create!(window_plan.to_params)
14
+
15
+ sequence do
16
+ concurrence do
17
+ window_plan.groups.each do |group|
18
+ plan_action(Actions::ForemanPatch::Round::Create, group, window)
19
+ end
20
+ end
21
+
22
+ plan_action(Actions::ForemanPatch::Window::Publish, window)
23
+ end
24
+
25
+ plan_self(window: window.to_action_input)
26
+ end
27
+
28
+ def run
29
+ output.update(window: window.to_action_input)
30
+ end
31
+
32
+ def window
33
+ @window = ::ForemanPatch::Window.find(input[:window][:id])
34
+ end
35
+
36
+ private
37
+
38
+ end
39
+ end
40
+ end
41
+ end