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,45 @@
1
+ module ForemanPatch
2
+ module PlansHelper
3
+
4
+ def plan_actions(plan)
5
+ links = []
6
+
7
+ links << link_to(_('Create Window'), new_plan_window_plan_path(plan_id: @plan.id),
8
+ class: 'btn btn-default',
9
+ title: _('Create a new window for this plan'))
10
+
11
+ links << link_to(_('Edit'), edit_plan_path(@plan),
12
+ class: 'btn btn-default',
13
+ title: _('Edit this plan'))
14
+
15
+ links << link_to(_('Run'), iterate_plan_path(@plan),
16
+ class: 'btn btn-primary',
17
+ title: _('Manually Iterate Plan'),
18
+ method: :post)
19
+
20
+ links
21
+ end
22
+
23
+ def plan_windows(plan, day)
24
+ day = (day - plan.start_date).to_i
25
+
26
+ plan.window_plans.select do |window|
27
+ window.start_day == day
28
+ end
29
+ end
30
+
31
+ def plan_window_actions(window)
32
+ actions = []
33
+
34
+ actions << link_to(_('Edit'), edit_window_plan_path(window))
35
+ actions << link_to(_('Delete'), hash_for_window_plan_path(id: window), data: { confirm: _('Are you sure?') }, action: :destroy)
36
+
37
+ actions
38
+ end
39
+
40
+ def plan_last_window_day(plan)
41
+ (plan.frequency.to_i / ActiveSupport::Duration::SECONDS_PER_DAY) - 1
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ module ForemanPatch
2
+ module TicketHelper
3
+
4
+ def ticket_link(window, options = {})
5
+ body = options.delete(:body) || window.ticket.label
6
+
7
+ link_to body, window.ticket.link, options
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module ForemanPatch
2
+ module WindowPatchingHelper
3
+
4
+ def rounds(window)
5
+ window.rounds.map do |round|
6
+ {
7
+ name: round.name,
8
+ link: round_path(round),
9
+ priority: round.priority,
10
+ hostsCount: round.invocations.count,
11
+ hostsLink: main_app.hosts_path(search: "patch_round_id = #{round.id}"),
12
+ status: round.status,
13
+ actions: []
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+
@@ -0,0 +1,13 @@
1
+ module ForemanPatch
2
+ module WindowPlansHelper
3
+
4
+ def plan_length(plan)
5
+ (plan.start_date - plan.end_date).to_i
6
+ end
7
+
8
+ def time_local_f(f, attr, options = {})
9
+ react_form_input('time', f, attr, options)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module ForemanPatch
2
+ module WindowsHelper
3
+
4
+ def round_move_buttons(group)
5
+ return 'TODO'
6
+ buttons = []
7
+
8
+ groups_hash = group.window.rounds.group_by(&:priority).to_hash
9
+
10
+ buttons.push(link_to(_('Move up'), hash_for_move_round_path(id: group, direction: :up), method: :post)) unless priority == 1
11
+ buttons.push(link_to(_('Move down'), hash_for_move_round_path(id: group, direction: :down), method: :post)) unless priority == last
12
+
13
+ action_buttons(*buttons) unless buttons.empty?
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Cycle
4
+ class Complete < Actions::EntryAction
5
+
6
+ def delay(delay_options, cycle)
7
+ action_subject(cycle)
8
+
9
+ super delay_options, cycle
10
+ end
11
+
12
+ def plan(cycle)
13
+ action_subject(cycle)
14
+
15
+ plan_self
16
+ end
17
+
18
+ def finalize
19
+ users = ::User.select { |user| user.receives?(:patch_cycle_completed) }.compact
20
+
21
+ begin
22
+ MailNotification[:patch_cycle_completed].deliver(users: users, cycle: cycle) unless users.blank?
23
+ rescue => error
24
+ Rails.logger.error(error)
25
+ end
26
+ end
27
+
28
+ def humanized_name
29
+ _('Complete Patch Cycle: %s') % input[:cycle][:name]
30
+ end
31
+
32
+ private
33
+
34
+ def cycle
35
+ @cycle ||= ::ForemanPatch::Cycle.find(input[:cycle][:id])
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,69 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Cycle
4
+ class Create < Actions::EntryAction
5
+
6
+ def resource_locks
7
+ :link
8
+ end
9
+
10
+ def plan(plan)
11
+ action_subject(plan)
12
+
13
+ cycle = ::ForemanPatch::Cycle.create!(plan.to_params)
14
+
15
+ concurrence do
16
+ plan.window_plans.each do |window_plan|
17
+ plan_action(Actions::ForemanPatch::Window::Create, window_plan, cycle)
18
+ end
19
+ end
20
+
21
+ plan.start_date = plan.next_cycle_start
22
+ plan.save!
23
+
24
+ plan_self(cycle: cycle.to_action_input)
25
+ end
26
+
27
+ def run
28
+ output.update(cycle: cycle.to_action_input)
29
+
30
+ users = ::User.select { |user| user.receives?(:patch_cycle_planned) }.compact
31
+
32
+ begin
33
+ MailNotification[:patch_cycle_planned].deliver(users: users, cycle: cycle) unless users.blank?
34
+ rescue => error
35
+ Rails.logger.error(error)
36
+ end
37
+ end
38
+
39
+ def finalize
40
+ plan = ::ForemanPatch::Plan.find(input[:plan][:id])
41
+
42
+ ::ForemanTasks.delay(Actions::ForemanPatch::Cycle::Initiate, delay_options, cycle, plan)
43
+
44
+ plan.iterate
45
+ end
46
+
47
+ def cycle
48
+ @cycle ||= ::ForemanPatch::Cycle.find(input[:cycle][:id])
49
+ end
50
+
51
+ def humanized_name
52
+ _('Create cycle: %s') % input[:plan][:name]
53
+ end
54
+
55
+ private
56
+
57
+ def delay_options
58
+ Time.use_zone(Setting[:patch_schedule_time_zone]) do
59
+ {
60
+ start_at: cycle.start_date.beginning_of_day,
61
+ }
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,68 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Cycle
4
+ class Initiate < Actions::EntryAction
5
+
6
+ def delay(delay_options, cycle, plan = nil)
7
+ input.update serialize_args(cycle: cycle)
8
+ add_missing_task_group(plan) if plan.present?
9
+
10
+ super delay_options, cycle
11
+ end
12
+
13
+ def plan(cycle, plan = nil)
14
+ input.update serialize_args(cycle: cycle)
15
+ add_missing_task_group(plan) if plan.present?
16
+
17
+ cycle.windows.each do |window|
18
+ plan_action(Actions::ForemanPatch::Window::ResolveHosts, window)
19
+ end
20
+ plan_self
21
+ end
22
+
23
+ def run
24
+ content_view_versions = cycle.hosts.map do |host|
25
+ host.content_view.version(host.lifecycle_environment)
26
+ end.uniq
27
+
28
+ content_view_versions.each do |version|
29
+ next unless available_content?(version)
30
+
31
+ ::ForemanTasks.async_task(Actions::ForemanPatch::Cycle::PrepareContent, version, _('Updating content for patch cycle: %s') % cycle.name)
32
+ end
33
+ end
34
+
35
+ def finalize
36
+ cycle.windows.each(&:schedule)
37
+
38
+ cycle.plan.iterate if cycle.plan.present?
39
+ end
40
+
41
+ def humanized_name
42
+ _('Initiating patch cycle: %s') % cycle.name
43
+ end
44
+
45
+ def cycle
46
+ @cycle ||= ::ForemanPatch::Cycle.find(input[:cycle][:id])
47
+ end
48
+
49
+ private
50
+
51
+ def available_content?(version)
52
+ version.available_packages.any? or
53
+ version.available_errata.any? or
54
+ ::Katello::Deb.in_repositories(version.library_repos).where.not(id: version.debs).any?
55
+ end
56
+
57
+ def add_missing_task_group(plan)
58
+ if plan.task_group.nil?
59
+ plan.task_group = ::ForemanPatch::PlanTaskGroup.create!
60
+ plan.save!
61
+ end
62
+ task.add_missing_task_groups(plan.task_group)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Cycle
4
+ class Plan < Actions::EntryAction
5
+
6
+ def delay(delay_options, plan)
7
+ input.update serialize_args(plan: plan)
8
+ add_missing_task_group(plan)
9
+
10
+ super delay_options, plan
11
+ end
12
+
13
+ def plan(plan)
14
+ input.update serialize_args(plan: plan)
15
+ add_missing_task_group(plan)
16
+
17
+ sequence do
18
+ creation = plan_action(::Actions::ForemanPatch::Cycle::Create, params(plan))
19
+
20
+ concurrence do
21
+ plan.window_plans.each do |window_plan|
22
+ plan_action(::Actions::ForemanPatch::Window::Plan, window_plan, creation.output[:cycle])
23
+ end
24
+ end
25
+
26
+ plan_self
27
+ end
28
+ end
29
+
30
+ def run
31
+ cycle_plan.start_date = cycle_plan.next_cycle_start
32
+ cycle_plan.save!
33
+ end
34
+
35
+ def finalize
36
+ cycle_plan.iterate if cycle_plan.active_count > 0
37
+ end
38
+
39
+ def humanized_name
40
+ _('Plan cycle: %s') % input[:plan][:name]
41
+ end
42
+
43
+ private
44
+
45
+ def cycle_plan
46
+ @cycle_plan ||= ::ForemanPatch::Plan.find(input[:plan][:id])
47
+ end
48
+
49
+ def cycle
50
+ @cycle ||= ::ForemanPatch::Cycle.find(input[:cycle][:id])
51
+ end
52
+
53
+ def params(plan)
54
+ {
55
+ plan_id: plan.id,
56
+ name: ::ForemanPatch::CycleNameGenerator.generate(plan),
57
+ start_date: plan.start_date.to_s,
58
+ end_date: (plan.next_cycle_start - 1.day).to_s,
59
+ }
60
+ end
61
+
62
+ def add_missing_task_group(plan)
63
+ if plan.task_group.nil?
64
+ plan.task_group = ::ForemanPatch::PlanTaskGroup.create!
65
+ plan.save!
66
+ end
67
+ task.add_missing_task_groups(plan.task_group)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,123 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Cycle
4
+ class PrepareContent < Actions::EntryAction
5
+ include ::Katello::ContentViewHelper
6
+
7
+ def humanized_name
8
+ _('Minor Version Update')
9
+ end
10
+
11
+ def plan(old_version, description)
12
+ action_subject(old_version.content_view)
13
+
14
+ new_minor = old_version.content_view.versions.where(major: old_version.major).maximum(:minor) + 1
15
+
16
+ components = []
17
+
18
+ sequence do
19
+ if old_version.content_view.composite?
20
+ components = update_components(old_version.components, description)
21
+ end
22
+
23
+ new_version = old_version.content_view.create_new_version(old_version.major, new_minor, components)
24
+
25
+ history = ::Katello::ContentViewHistory.create!(content_view_version: new_version,
26
+ user: ::User.current.login,
27
+ action: ::Katello::ContentViewHistory.actions[:publish],
28
+ status: ::Katello::ContentViewHistory::IN_PROGRESS,
29
+ task: self.task,
30
+ notes: description)
31
+
32
+ repositories = collect_repositories(old_version, components)
33
+
34
+ repository_mapping = plan_action(Actions::Katello::ContentViewVersion::CreateRepos,
35
+ new_version, repositories).repository_mapping
36
+
37
+ separated_repo_map = separated_repo_mapping(repository_mapping, true)
38
+
39
+ if separated_repo_map[:pulp3_yum_multicopy].keys.flatten.present? &&
40
+ SmartProxy.pulp_primary.pulp3_support?(separated_repo_map[:pulp3_yum_multicopy].keys.flatten.first)
41
+
42
+ plan_action(Actions::Katello::Repository::MultiCloneToVersion, separated_repo_map[:pulp3_yum_multicopy], new_version)
43
+ end
44
+
45
+ concurrence do
46
+ repositories.each do |repository|
47
+ plan_action(Actions::Katello::Repository::CloneToVersion,
48
+ repository, new_version, repository_mapping[repository])
49
+ end
50
+ end
51
+
52
+ plan_self(new_version_id: new_version.id,
53
+ history_id: history.id,
54
+ old_version_id: old_version.id)
55
+ plan_action(Actions::Katello::ContentView::Promote, new_version, old_version.environments, true)
56
+ end
57
+ end
58
+
59
+ def finalize
60
+ new_version.update_content_counts!
61
+
62
+ history.status = ::Katello::ContentViewHistory::SUCCESSFUL
63
+ history.save!
64
+ end
65
+
66
+ def new_version
67
+ @new_version ||= ::Katello::ContentViewVersion.find(input[:new_version_id])
68
+ end
69
+
70
+ private
71
+
72
+ def old_version
73
+ @old_version ||= ::Katello::ContentViewVersion.find(input[:old_version_id])
74
+ end
75
+
76
+ def history
77
+ @history ||= ::Katello::ContentViewHistory.find(input[:history_id])
78
+ end
79
+
80
+ def available_content?(version)
81
+ version.available_packages.any? or
82
+ version.available_errata.any? or
83
+ ::Katello::Deb.in_repositories(version.library_repos).where.not(id: version.debs).any?
84
+ end
85
+
86
+ def collect_repositories(version, components)
87
+ repositories = []
88
+ if version.content_view.composite?
89
+ ids = components.flat_map { |component| component.repositories.archived }.map(&:id)
90
+ repositories = ::Katello::Repository.where(id: ids)
91
+ else
92
+ repositories = version.library_repos
93
+ end
94
+ repositories.map do |repo|
95
+ if repo.is_a? Array
96
+ repo
97
+ else
98
+ [repo]
99
+ end
100
+ end
101
+ end
102
+
103
+ def update_components(components, description)
104
+ new_components = []
105
+ concurrence do
106
+ components.each do |component|
107
+ if available_content?(component)
108
+ new_components << plan_action(Actions::ForemanPatch::Cycle::PrepareContent,
109
+ component, description).new_version
110
+ else
111
+ new_components << component
112
+ end
113
+ end
114
+ end
115
+ new_components
116
+ end
117
+
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+
@@ -0,0 +1,32 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Host
4
+ class Reschedule < Actions::Base
5
+
6
+ def plan(*hosts, **options)
7
+ hosts = hosts.flatten
8
+ input.update(**options, hosts: hosts.map(&:to_action_input))
9
+
10
+ statuses = ['planned']
11
+ statuses << 'scheduled' if options.fetch(:include_active, false)
12
+
13
+ # this query must be converted to array otherwise changes will alter the results
14
+ windows = ::ForemanPatch::Window.with_hosts(hosts).with_status(statuses).to_a
15
+
16
+ sequence do
17
+ ::ForemanPatch::Invocation.in_windows(windows).where(host: hosts).each do |invocation|
18
+ plan_action(Actions::ForemanPatch::Invocation::Reschedule, invocation)
19
+ end
20
+ ::ForemanPatch::Round.in_windows(windows).missing_hosts(hosts).each do |round|
21
+ plan_action(Actions::ForemanPatch::Round::AddMissingHosts, round, hosts)
22
+ end
23
+
24
+ plan_action(Actions::BulkAction, Actions::ForemanPatch::Window::Publish, windows) unless windows.empty?
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,135 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Invocation
4
+ class Action < ::Actions::EntryAction
5
+ include ::Actions::Helpers::WithDelegatedAction
6
+
7
+ class TemplateInvocationInputValue
8
+ attr_reader :template_invocation, :template_input, :value
9
+
10
+ def initialize(invocation, input, value)
11
+ @template_invocation = invocation
12
+ @template_input = input
13
+ @value = value
14
+ end
15
+ end
16
+
17
+ class TemplateInvocation
18
+ attr_reader :template, :input_values
19
+
20
+ def initialize(template, **input_values)
21
+ @template = template
22
+
23
+ @input_values = template.template_inputs_with_foreign.map do |template_input|
24
+ TemplateInvocationInputValue.new(self, template_input, input_values[template_input.name.intern])
25
+ end
26
+ end
27
+
28
+ def effective_user
29
+ if template.provider.supports_effective_user?
30
+ Setting[:remote_execution_effective_user]
31
+ else
32
+ nil
33
+ end
34
+ end
35
+ end
36
+
37
+ def resource_locks
38
+ :link
39
+ end
40
+
41
+ def plan(host, feature_name, required = true, **input_values)
42
+ action_subject(host, feature_name: feature_name, required: required, **input_values)
43
+
44
+ invocation = TemplateInvocation.new(template, **input_values)
45
+
46
+ provider = template.provider
47
+ proxy_selector = provider.required_proxy_selector_for(template) || ::RemoteExecutionProxySelector.new
48
+
49
+ proxy = proxy_selector.determine_proxy(host, template.provider_type.to_s)
50
+
51
+ renderer = InputTemplateRenderer.new(template, host, invocation)
52
+ script = renderer.render
53
+ raise _('Failed rendering template: %s') % renderer.error_message unless script
54
+
55
+ additional_options = {
56
+ hostname: provider.find_ip_or_hostname(host),
57
+ execution_timeout_interval: template.execution_timeout_interval,
58
+ script: script,
59
+ secrets: provider.secrets(host),
60
+ }
61
+ action_options = provider.proxy_command_options(invocation, host).merge(additional_options)
62
+
63
+ sequence do
64
+ plan_delegated_action(proxy, provider.proxy_action_class, action_options)
65
+ plan_self
66
+ end
67
+ end
68
+
69
+ def run
70
+ if exit_status != 0
71
+ users = ::User.select { |user| user.receives?(:patch_invocation_failure) }.compact
72
+
73
+ MailNotification[:patch_invocation_failure].deliver(users: users, host: host, output: live_output) unless users.blank?
74
+ fail(_('Patch step failed: %{step}') % {step: humanized_name})
75
+ end
76
+ end
77
+
78
+ def exit_status
79
+ delegated_output[:exit_status]
80
+ end
81
+
82
+ def feature
83
+ @feature ||= ::RemoteExecutionFeature.feature(input[:feature_name])
84
+ end
85
+
86
+ def template
87
+ @template ||= feature.job_template
88
+ end
89
+
90
+ def live_output
91
+ continuous_output.sort!
92
+ continuous_output.raw_outputs
93
+ end
94
+
95
+ def continuous_output_providers
96
+ super << self
97
+ end
98
+
99
+ def fill_continuous_output(continuous_output)
100
+ delegated_output.fetch('result', []).each do |raw_output|
101
+ continuous_output.add_raw_output(raw_output)
102
+ end
103
+
104
+ final_timestamp = (continuous_output.last_timestamp || task.ended_at).to_f + 1
105
+
106
+ fill_planning_errors_to_continuous_output(continuous_output) unless exit_status
107
+
108
+ continuous_output.add_output(_('Exit status: %s') % exit_status, 'stdout', final_timestamp) if exit_status
109
+ rescue => e
110
+ continuous_output.add_exception(_('Error loading data from proxy'), e)
111
+ end
112
+
113
+ def required?
114
+ input.fetch(:required, true)
115
+ end
116
+
117
+ def humanized_name
118
+ input[:feature_name].titleize
119
+ end
120
+
121
+ def rescue_strategy_for_self
122
+ required? ? ::Dynflow::Action::Rescue::Fail : ::Dynflow::Action::Rescue::Skip
123
+ end
124
+
125
+ private
126
+
127
+ def host
128
+ @host ||= ::Host.find(input[:host][:id])
129
+ end
130
+
131
+ end
132
+ end
133
+ end
134
+ end
135
+