foreman_patch 1.1.6.alpha4 → 1.2.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_patch/api/v2/invocations_controller.rb +1 -23
  3. data/app/controllers/foreman_patch/concerns/hosts_controller_extensions.rb +41 -35
  4. data/app/lib/actions/foreman_patch/cycle/complete.rb +41 -0
  5. data/app/lib/actions/foreman_patch/cycle/create.rb +1 -5
  6. data/app/lib/actions/foreman_patch/cycle/initiate.rb +1 -5
  7. data/app/lib/actions/foreman_patch/cycle/plan.rb +66 -0
  8. data/app/lib/actions/foreman_patch/invocation/action.rb +29 -23
  9. data/app/lib/actions/foreman_patch/invocation/patch.rb +8 -16
  10. data/app/lib/actions/foreman_patch/invocation/wait_for_host.rb +29 -4
  11. data/app/lib/actions/foreman_patch/round/patch.rb +1 -5
  12. data/app/lib/actions/foreman_patch/round/plan.rb +33 -0
  13. data/app/lib/actions/foreman_patch/window/plan.rb +43 -0
  14. data/app/lib/actions/foreman_patch/window/publish.rb +1 -5
  15. data/app/lib/actions/foreman_patch/window/resolve_hosts.rb +1 -5
  16. data/app/models/foreman_patch/invocation.rb +4 -4
  17. data/app/models/foreman_patch/round.rb +23 -4
  18. data/app/models/setting/patching.rb +57 -0
  19. data/app/services/foreman_patch/ticket/api.rb +1 -2
  20. data/app/views/foreman_patch/api/v2/invocations/base.json.rabl +1 -1
  21. data/app/views/foreman_patch/api/v2/invocations/phase.json.rabl +7 -0
  22. data/app/views/foreman_patch/api/v2/invocations/show.json.rabl +2 -2
  23. data/app/views/foreman_patch/api/v2/rounds/base.json.rabl +1 -1
  24. data/app/views/foreman_patch/api/v2/rounds/status.json.rabl +8 -2
  25. data/app/views/foreman_patch/groups/index.html.erb +1 -1
  26. data/app/views/foreman_patch/layouts/react.html.erb +1 -1
  27. data/app/views/templates/ensure_services.erb +4 -7
  28. data/config/api_routes.rb +24 -28
  29. data/config/routes/mount_engine.rb +3 -0
  30. data/config/routes/overrides.rb +10 -0
  31. data/config/routes.rb +29 -40
  32. data/db/seeds.d/100-assign_features_with_templates.rb +12 -6
  33. data/lib/foreman_patch/engine.rb +46 -11
  34. data/lib/foreman_patch/plugin.rb +47 -0
  35. data/lib/foreman_patch/version.rb +1 -1
  36. data/lib/foreman_patch.rb +2 -3
  37. data/locale/en/foreman_patch.po +1 -1
  38. data/locale/foreman_patch.pot +1 -1
  39. data/locale/gemspec.rb +1 -1
  40. data/package.json +9 -20
  41. data/public/assets/foreman_patch/cycle_plans-e5667e178ba389908f5c815b24ec0ea77c340849d56bc39c5ce72bb626bd446a.scss.gz +0 -0
  42. data/public/assets/foreman_patch/cycle_plans-ff3d252119622a68828ff70f4a97328303963002237dbf850e92d6a706e93667.scss.gz +0 -0
  43. data/public/assets/foreman_patch/foreman_patch-be2e2ba89548f4a490612e8a6cd1cdebc0473be89f8023a3df7612f05a75d301.css +1 -0
  44. data/public/assets/foreman_patch/foreman_patch-be2e2ba89548f4a490612e8a6cd1cdebc0473be89f8023a3df7612f05a75d301.css.gz +0 -0
  45. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css +1 -0
  46. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css.gz +0 -0
  47. data/public/assets/foreman_patch/foreman_patch.json +1 -1
  48. data/public/assets/foreman_patch/plan_edit_windows-9ba20f84f3ecf2c4eb903acd57d30ee3e16f023a79db30bc614aa22f26442ce3.js +1 -0
  49. data/public/assets/foreman_patch/plan_edit_windows-9ba20f84f3ecf2c4eb903acd57d30ee3e16f023a79db30bc614aa22f26442ce3.js.gz +0 -0
  50. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js +1 -0
  51. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js.gz +0 -0
  52. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.css.gz +0 -0
  53. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js +6 -0
  54. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.gz +0 -0
  55. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.map +1 -0
  56. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.map.gz +0 -0
  57. data/public/webpack/foreman_patch/{foreman_patch.css → foreman_patch-4a4e1a59d74af09c4b8b.css} +1 -1
  58. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.css.gz +0 -0
  59. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js +6 -0
  60. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.gz +0 -0
  61. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.map +1 -0
  62. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.map.gz +0 -0
  63. data/public/webpack/foreman_patch/manifest.json +14 -13
  64. data/public/webpack/foreman_patch/manifest.json.gz +0 -0
  65. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js +2 -0
  66. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.gz +0 -0
  67. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map +1 -0
  68. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map.gz +0 -0
  69. data/webpack/components/Invocation/Invocation.js +47 -0
  70. data/webpack/{src/Components → components}/Invocation/InvocationSelectors.js +3 -0
  71. data/webpack/components/Invocation/index.js +36 -0
  72. data/webpack/components/Invocations/Invocations.js +16 -48
  73. data/webpack/components/Invocations/InvocationsPage.js +1 -24
  74. data/webpack/components/Invocations/InvocationsSelectors.js +1 -1
  75. data/webpack/components/Invocations/components/{InvocationActions.js → InvocationItem.js} +16 -4
  76. data/webpack/components/Invocations/index.js +12 -95
  77. data/webpack/components/RoundProgress/AggregateStatus.js +5 -6
  78. data/webpack/components/RoundProgress/RoundProgress.js +6 -7
  79. data/webpack/components/RoundProgress/RoundProgressSelectors.js +2 -3
  80. data/webpack/components/common/Calendar/Calendar.js +4 -5
  81. data/webpack/components/common/Terminal/OutputLine.js +26 -0
  82. data/webpack/components/common/Terminal/Terminal.js +115 -0
  83. data/webpack/components/common/Terminal/Terminal.scss +47 -0
  84. data/webpack/index.js +0 -3
  85. metadata +92 -49
  86. data/app/controllers/foreman_patch/react_controller.rb +0 -12
  87. data/app/lib/actions/foreman_patch/invocation/process_logging.rb +0 -44
  88. data/app/lib/actions/foreman_patch/invocation/proxy_action.rb +0 -52
  89. data/app/models/foreman_patch/event.rb +0 -13
  90. data/app/views/foreman_patch/api/v2/invocations/event.json.rabl +0 -3
  91. data/db/migrate/20230706092400_nullify_group_on_delete.rb +0 -11
  92. data/db/migrate/20230707102800_create_invocation_events.rb +0 -16
  93. data/lib/foreman_patch/register.rb +0 -119
  94. data/public/assets/foreman_patch/calendar-b5391efda77239c4a4894e9f03f34610f6c8e2e748b2a147febfea814b857cdc.scss.gz +0 -0
  95. data/public/assets/foreman_patch/foreman_patch-410cf04bf9b09e65fee034cc3f2dd74acf2524abf881c6d6e559d5c62a615faf.css +0 -11
  96. data/public/assets/foreman_patch/foreman_patch-410cf04bf9b09e65fee034cc3f2dd74acf2524abf881c6d6e559d5c62a615faf.css.gz +0 -0
  97. data/public/assets/foreman_patch/foreman_patch-84845e54f06d3a11189828e656432d587c7312358cdf694753da7b78b7dabcee.css +0 -11
  98. data/public/assets/foreman_patch/foreman_patch-84845e54f06d3a11189828e656432d587c7312358cdf694753da7b78b7dabcee.css.gz +0 -0
  99. data/public/assets/foreman_patch/foreman_patch-a76c5fd10a5795e97c5ae4c222bfdf4ab88da49d6a7659175dba79f8fc62ab47.css +0 -82
  100. data/public/assets/foreman_patch/foreman_patch-a76c5fd10a5795e97c5ae4c222bfdf4ab88da49d6a7659175dba79f8fc62ab47.css.gz +0 -0
  101. data/public/assets/foreman_patch/plan_edit_windows-2eb04c7e83fa62797b0a14364d3ff5b3c4336983603fdc5a276b5464eeba7e60.js +0 -9
  102. data/public/assets/foreman_patch/plan_edit_windows-2eb04c7e83fa62797b0a14364d3ff5b3c4336983603fdc5a276b5464eeba7e60.js.gz +0 -0
  103. data/public/assets/foreman_patch/plan_edit_windows-ddedd3e70fb6ef761f636be2b7b35286e86d68e126bfc37294f9365a5171a928.js +0 -9
  104. data/public/assets/foreman_patch/plan_edit_windows-ddedd3e70fb6ef761f636be2b7b35286e86d68e126bfc37294f9365a5171a928.js.gz +0 -0
  105. data/public/webpack/foreman_patch/bundle.js +0 -34173
  106. data/public/webpack/foreman_patch/foreman_patch.js +0 -34366
  107. data/public/webpack/foreman_patch/foreman_patch:global.css +0 -1
  108. data/public/webpack/foreman_patch/foreman_patch:global.js +0 -32098
  109. data/public/webpack/foreman_patch/vendor.js +0 -5201
  110. data/webpack/components/common/Calendar/Calendar.css +0 -76
  111. data/webpack/components/common/Table/index.js +0 -28
  112. data/webpack/global_index.js +0 -16
  113. data/webpack/src/Components/Invocation/Invocation.js +0 -67
  114. data/webpack/src/Components/Invocation/InvocationLogFooter.js +0 -30
  115. data/webpack/src/Components/Invocation/InvocationLogToolbar.js +0 -80
  116. data/webpack/src/Components/Invocation/index.js +0 -62
  117. data/webpack/src/Components/InvocationStatus.js +0 -50
  118. data/webpack/src/Components/Loading.js +0 -51
  119. data/webpack/src/Extends/index.js +0 -15
  120. data/webpack/src/Router/routes.js +0 -5
  121. data/webpack/src/reducers.js +0 -7
  122. /data/public/webpack/foreman_patch/{bundle.css → bundle-e45c4bb530e40506f2da.css} +0 -0
  123. /data/webpack/{src/Components → components}/Invocation/InvocationActions.js +0 -0
  124. /data/webpack/{src/Components → components}/Invocation/InvocationConsts.js +0 -0
  125. /data/webpack/components/Invocations/{Invocations.css → InvocationsPage.scss} +0 -0
  126. /data/{public/assets/foreman_patch/calendar-b5391efda77239c4a4894e9f03f34610f6c8e2e748b2a147febfea814b857cdc.scss → webpack/components/common/Calendar/Calendar.scss} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a0c418f7823f9284b25ba359c284ac4eb6f090e1826b32759ff11c4c9930a20
4
- data.tar.gz: 52f7f32b37f8ab528b6946d17023ed613cf874ba913efc8b42b3c38dc13974bb
3
+ metadata.gz: 900b05514ac7bb3e7cec9d95b0ad2b982feea0081dd73be23ab17041cb44c95d
4
+ data.tar.gz: ebdd75375aaf6acebd342f0f00e7be6658ec5399c9172f84b50263fe2b22573a
5
5
  SHA512:
6
- metadata.gz: fcddad96ea62cb31521ca728b418fc2f33fbbc9a167d06270fc4a8d45a5bb6d23915b9686af28c86203d9c4fdd48e62f2c8cf3afdb8c1695da49c8818df89cbb
7
- data.tar.gz: 81d7bf80181451853b12c593cfac3bca9e662da2db237e7f54ce780a3b1a41e03a112a34b4fc81ad7bf5cd54096c85d22f7bbfa72b7c602603ca120f910ceb97
6
+ metadata.gz: d01c259cd2d57f7e4febcac38b3d9161c5ae3bd9fa84df2ef3f8cb9443a79350b7f6cc007c47aab787478f5516a70661fdae4777e13e95f8e4f25b459da0b449
7
+ data.tar.gz: 78a7fd36dd08a76f613bbf839ebbff94d5e7e7d31766276ff3f1a4b42f4a2555a316cbf377a8ec6e63610914f51f37447f5b7446b987c29efb310a7fffc5dd7a
@@ -23,6 +23,7 @@ module ForemanPatch
23
23
  api :GET, '/invocations/:id', N_('Get details of an invocation')
24
24
  param :id, :identifier, required: true
25
25
  def show
26
+ @invocation = ForemanPatch::Invocation.find(params[:id])
26
27
  end
27
28
 
28
29
  api :PUT, '/invocations/:id', N_('Move the invocation to another round')
@@ -34,29 +35,6 @@ module ForemanPatch
34
35
  process_response @invocation.update(invocation_params)
35
36
  end
36
37
 
37
- api :PUT, '/invocations/move', N_('Move invocations to another round')
38
- param :ids, Array, required: true, desc: N_('List of invocation ids')
39
- param :round_id, Integer, required: true, desc: N_('Id of the destination round')
40
- def move
41
- @invocations = ForemanPatch::Invocation.where(id: params[:ids])
42
-
43
- @errors = []
44
- @invocations.each do |invocation|
45
- round = invocation.round.cycle.rounds.find(params[:round_id])
46
- invocation.update(round: round)
47
- rescue
48
- end
49
-
50
- @invocations = ForemanPatch::Invocation.where(id: params[:ids], round_id: params[:round_id])
51
- end
52
-
53
- api :PUT, '/invocations/cancel', N_('Cancel invocations')
54
- param :ids, Array, required: true, desc: N_('List of invocation ids')
55
- def cancel
56
- @invocations = ForemanPatch::Invocation.where(id: params[:ids])
57
- @invocations.update_all(status: 'cancelled')
58
- end
59
-
60
38
  api :DELETE, 'invocations/:id', N_('Delete the patch invocation')
61
39
  param :id, :identifier, required: true
62
40
  def destroy
@@ -3,52 +3,58 @@ module ForemanPatch
3
3
  module HostsControllerExtensions
4
4
  extend ActiveSupport::Concern
5
5
 
6
- MULTIPLE_EDIT_ACTIONS = %w[select_multiple_patch_group, update_multiple_patch_group].freeze
6
+ module Overrides
7
+ def action_permission
8
+ case params[:action]
9
+ when 'select_multiple_patch_group', 'update_multiple_patch_group'
10
+ :edit
11
+ else
12
+ super
13
+ end
14
+ end
15
+ end
7
16
 
8
17
  included do
9
- before_action :find_multiple_for_foreman_patch_extensions, only: MULTIPLE_EDIT_ACTIONS
10
- after_action :reschedule_patching, only: :update
18
+ prepend Overrides
11
19
 
12
- define_action_permission MULTIPLE_EDIT_ACTIONS, :edit
13
-
14
- helper ForemanPatch::HostsHelper
15
- end
16
-
17
- def select_multiple_patch_group
18
- end
20
+ after_action :reschedule_patching, only: :update
19
21
 
20
- def update_multiple_patch_group
21
- if (params['patch_group']['id'].blank?)
22
- @hosts.each do |host|
23
- group_facet = host.group_facet
24
- group_facet.group = nil unless group_facet.blank?
25
- host.save!
26
- end
27
- else
28
- patch_group = ForemanPatch::Group.find(params['patch_group']['id'])
22
+ def select_multiple_patch_group
23
+ find_multiple
24
+ end
29
25
 
30
- @hosts.each do |host|
31
- group_facet = host.group_facet || host.build_group_facet
32
- group_facet.group = patch_group
33
- host.save!
26
+ def update_multiple_patch_group
27
+ find_multiple
28
+
29
+ if (params['patch_group']['id'].blank?)
30
+ @hosts.each do |host|
31
+ group_facet = host.group_facet
32
+ group_facet.group = nil unless group_facet.blank?
33
+ host.save!
34
+ end
35
+ else
36
+ patch_group = ForemanPatch::Group.find(params['patch_group']['id'])
37
+
38
+ @hosts.each do |host|
39
+ group_facet = host.group_facet || host.build_group_facet
40
+ group_facet.group = patch_group
41
+ host.save!
42
+ end
34
43
  end
35
- end
36
44
 
37
- ForemanTasks.async_task(Actions::ForemanPatch::Host::Reschedule, @hosts, include_active: params['patch_group']['include_active'])
45
+ ForemanTasks.async_task(Actions::ForemanPatch::Host::Reschedule, @hosts, include_active: params['patch_group']['include_active'])
38
46
 
39
- success _('Updated hosts: changed patch group')
40
- redirect_back_or_to hosts_path
41
- end
47
+ success _('Updated hosts: changed patch group')
48
+ redirect_back_or_to hosts_path
49
+ end
42
50
 
43
- def reschedule_patching
44
- return if @host.group_facet.nil?
45
- return unless @host.group_facet.saved_change_to_attribute?(:group_id)
51
+ def reschedule_patching
52
+ return if @host.group_facet.nil?
53
+ return unless @host.group_facet.saved_change_to_attribute?(:group_id)
46
54
 
47
- ForemanTasks.async_task(Actions::ForemanPatch::Host::Reschedule, @host)
48
- end
55
+ ForemanTasks.async_task(Actions::ForemanPatch::Host::Reschedule, @host)
56
+ end
49
57
 
50
- def find_multiple_for_foreman_patch_extensions
51
- find_multiple
52
58
  end
53
59
  end
54
60
  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
@@ -49,11 +49,7 @@ module Actions
49
49
  end
50
50
 
51
51
  def humanized_name
52
- _('Create cycle:')
53
- end
54
-
55
- def humanized_input
56
- input.dig(:plan, :name)
52
+ _('Create cycle: %s') % input[:plan][:name]
57
53
  end
58
54
 
59
55
  private
@@ -40,11 +40,7 @@ module Actions
40
40
  end
41
41
 
42
42
  def humanized_name
43
- _('Initiating patch cycle:')
44
- end
45
-
46
- def humanized_input
47
- cycle.name
43
+ _('Initiating patch cycle: %s') % cycle.name
48
44
  end
49
45
 
50
46
  def cycle
@@ -0,0 +1,66 @@
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
+ plan_action(::Actions::ForemanPatch::Cycle::Create, plan)
19
+ plan_self
20
+ end
21
+ end
22
+
23
+ def run
24
+ cycle_plan.start_date = cycle_plan.next_cycle_start
25
+ cycle_plan.save!
26
+ end
27
+
28
+ def finalize
29
+ cycle_plan.iterate if cycle_plan.active_count > 0
30
+ end
31
+
32
+ def humanized_name
33
+ _('Plan cycle: %s') % input[:plan][:name]
34
+ end
35
+
36
+ private
37
+
38
+ def cycle_plan
39
+ @cycle_plan ||= ::ForemanPatch::Plan.find(input[:plan][:id])
40
+ end
41
+
42
+ def cycle
43
+ @cycle ||= ::ForemanPatch::Cycle.find(input[:cycle][:id])
44
+ end
45
+
46
+ def params(plan)
47
+ {
48
+ plan_id: plan.id,
49
+ name: ::ForemanPatch::CycleNameGenerator.generate(plan),
50
+ start_date: plan.start_date.to_s,
51
+ end_date: (plan.next_cycle_start - 1.day).to_s,
52
+ }
53
+ end
54
+
55
+ def add_missing_task_group(plan)
56
+ if plan.task_group.nil?
57
+ plan.task_group = ::ForemanPatch::PlanTaskGroup.create!
58
+ plan.save!
59
+ end
60
+ task.add_missing_task_groups(plan.task_group)
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -46,7 +46,7 @@ module Actions
46
46
  provider = template.provider
47
47
  proxy_selector = provider.required_proxy_selector_for(template) || ::RemoteExecutionProxySelector.new
48
48
 
49
- proxy = determine_proxy!(proxy_selector, template.provider_type.to_s, host)
49
+ proxy = proxy_selector.determine_proxy(host, template.provider_type.to_s)
50
50
 
51
51
  renderer = InputTemplateRenderer.new(template, host, invocation)
52
52
  script = renderer.render
@@ -61,7 +61,7 @@ module Actions
61
61
  action_options = provider.proxy_command_options(invocation, host).merge(additional_options)
62
62
 
63
63
  sequence do
64
- plan_action(::Actions::ForemanPatch::Invocation::ProxyAction, proxy, provider.proxy_action_class, action_options)
64
+ plan_delegated_action(proxy, provider.proxy_action_class, action_options)
65
65
  plan_self
66
66
  end
67
67
  end
@@ -87,10 +87,37 @@ module Actions
87
87
  @template ||= feature.job_template
88
88
  end
89
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
+
90
113
  def required?
91
114
  input.fetch(:required, true)
92
115
  end
93
116
 
117
+ def humanized_name
118
+ input[:feature_name].titleize
119
+ end
120
+
94
121
  def rescue_strategy_for_self
95
122
  required? ? ::Dynflow::Action::Rescue::Fail : ::Dynflow::Action::Rescue::Skip
96
123
  end
@@ -101,27 +128,6 @@ module Actions
101
128
  @host ||= ::Host.find(input[:host][:id])
102
129
  end
103
130
 
104
- def determine_proxy!(proxy_selector, provider, host)
105
- proxy = proxy_selector.determine_proxy(host, provider)
106
- if proxy == :not_available
107
- offline_proxies = proxy_selector.offline
108
- settings = { count: offline_proxies.count, proxy_names: offline_proxies.map(&:name).join(', ') }
109
- raise n_('The only applicable proxy %{proxy_names} is down',
110
- 'All %{count} applicable proxies are down. Tried %{proxy_names}',
111
- offline_proxies.count) % settings
112
- elsif proxy == :not_defined
113
- settings = {
114
- global_proxy: 'remote_execution_global_proxy',
115
- fallback_proxy: 'remote_execution_fallback_proxy',
116
- provider: provider,
117
- }
118
-
119
- raise _('Could not use any proxy for the %{provider} job. Consider configuring %{global_proxy}, ' +
120
- '%{fallback_proxy} in settings') % settings
121
- end
122
- proxy
123
- end
124
-
125
131
  end
126
132
  end
127
133
  end
@@ -3,7 +3,6 @@ module Actions
3
3
  module Invocation
4
4
  class Patch < Actions::EntryAction
5
5
  include ::Actions::Helpers::WithContinuousOutput
6
- include ::Actions::ForemanPatch::Invocation::ProcessLogging
7
6
 
8
7
  execution_plan_hooks.use :update_status, on: ::Dynflow::ExecutionPlan.states
9
8
 
@@ -31,6 +30,7 @@ module Actions
31
30
 
32
31
  def update_status(execution_plan)
33
32
  return unless root_action?
33
+ return if input[:invocation_id].nil?
34
34
 
35
35
  case execution_plan.state
36
36
  when :scheduled, :pending, :planning, :planned
@@ -53,16 +53,8 @@ module Actions
53
53
  end
54
54
 
55
55
  def continuous_output_providers
56
- super << self
57
- end
58
-
59
- def fill_continuous_output(continuous_output)
60
- invocation.events.order(:sequence).find_each do |output|
61
- if output.event_type == 'exit'
62
- continuous_output.add_output(_('Exit status: %s') % output.event, 'stdout', output.timestamp)
63
- else
64
- continuous_output.add_raw_output(output.as_raw_continuous_output)
65
- end
56
+ planned_actions.select do |action|
57
+ action.respond_to?(:fill_continuous_output)
66
58
  end
67
59
  end
68
60
 
@@ -80,11 +72,7 @@ module Actions
80
72
  end
81
73
 
82
74
  def humanized_name
83
- _('Patch:')
84
- end
85
-
86
- def humanized_input
87
- host.name
75
+ _('Patch %s') % host.name
88
76
  end
89
77
 
90
78
  private
@@ -93,6 +81,10 @@ module Actions
93
81
  @host ||= ::Host.find(input[:host][:id])
94
82
  end
95
83
 
84
+ def invocation
85
+ @invocation ||= ::ForemanPatch::Invocation.find(input[:invocation_id])
86
+ end
87
+
96
88
  def failed_action
97
89
  planned_actions.find do |action|
98
90
  action.steps.compact.any? { |step| [:error, :skipped].include? step.state }
@@ -2,8 +2,8 @@ module Actions
2
2
  module ForemanPatch
3
3
  module Invocation
4
4
  class WaitForHost < Actions::EntryAction
5
+ include Actions::Helpers::WithContinuousOutput
5
6
  include Dynflow::Action::Polling
6
- include ::Actions::ForemanPatch::Invocation::ProcessLogging
7
7
 
8
8
  def plan(host)
9
9
  action_subject(host)
@@ -31,7 +31,7 @@ module Actions
31
31
  status = 'starting'
32
32
  ensure
33
33
  socket.close if socket
34
- log_invocation_event("Poll result: #{status}")
34
+ add_output("Poll result: #{status}")
35
35
  end
36
36
 
37
37
  def poll_intervals
@@ -46,15 +46,30 @@ module Actions
46
46
  end
47
47
 
48
48
  def on_finish
49
- log_invocation_event(_('Host is up'), 'stdout') if external_task == 'available'
49
+ add_output(_('Host is up'), 'stdout') if external_task == 'available'
50
50
  end
51
51
 
52
52
  def process_timeout
53
- log_invocation_event(_('Server did not respond withing alloted time after restart.'), 'stderr')
53
+ add_output(_('Server did not respond withing alloted time after restart.'), 'stderr')
54
54
 
55
55
  self.external_task = 'timeout'
56
56
  end
57
57
 
58
+ def live_output
59
+ continuous_output.sort!
60
+ continuous_output.raw_outputs
61
+ end
62
+
63
+ def continuous_output_providers
64
+ super << self
65
+ end
66
+
67
+ def fill_continuous_output(continuous_output)
68
+ output.fetch('result', []).each do |raw_output|
69
+ continuous_output.add_raw_output(raw_output)
70
+ end
71
+ end
72
+
58
73
  private
59
74
 
60
75
  def host
@@ -65,6 +80,16 @@ module Actions
65
80
  external_task == 'starting'
66
81
  end
67
82
 
83
+ def add_output(message, type = 'debug', timestamp = Time.now.getlocal)
84
+ formatted_output = {
85
+ output_type: type,
86
+ output: message,
87
+ timestamp: timestamp.to_f
88
+ }
89
+
90
+ output[:result] = [] if output[:result].nil?
91
+ output[:result] << formatted_output
92
+ end
68
93
  end
69
94
  end
70
95
  end
@@ -72,11 +72,7 @@ module Actions
72
72
  end
73
73
 
74
74
  def humanized_name
75
- 'Patch Group:'
76
- end
77
-
78
- def humanized_input
79
- round.name
75
+ 'Patch Group: %s' % round.name
80
76
  end
81
77
 
82
78
  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, 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,43 @@
1
+ module Actions
2
+ module ForemanPatch
3
+ module Window
4
+ class Plan < Actions::EntryAction
5
+
6
+ def plan(window_plan, cycle)
7
+ input.update serialize_args(window_plan: window_plan, cycle: cycle)
8
+
9
+ sequence do
10
+ action = plan_action(::Actions::ForemanPatch::Window::Create, window_plan, cycle)
11
+
12
+ concurrence do
13
+ window_plan.groups.each do |group|
14
+ plan_action(::Actions::ForemanPatch::Round::Plan, group, action.output[:window])
15
+ end
16
+ end
17
+
18
+ plan_action(::Actions::ForemanPatch::Window::Publish, action.output[:window])
19
+ end
20
+ end
21
+
22
+ def humanized_name
23
+ _('Plan window: %s') % input[:window_plan][:name]
24
+ end
25
+
26
+ private
27
+
28
+ def params(window_plan, cycle)
29
+ {
30
+ cycle: cycle,
31
+ name: window_plan.name,
32
+ description: window_plan.description,
33
+ start_at: window_plan.start_at.to_s,
34
+ end_by: window_plan.end_by.to_s,
35
+ }
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+
@@ -23,11 +23,7 @@ module Actions
23
23
  end
24
24
 
25
25
  def humanized_name
26
- _('Publish ticket for:')
27
- end
28
-
29
- def humanized_input
30
- window.name
26
+ _('Publish ticket for %s') % window.name
31
27
  end
32
28
 
33
29
  end
@@ -22,11 +22,7 @@ module Actions
22
22
  end
23
23
 
24
24
  def humanized_name
25
- _('Resolve Hosts for:')
26
- end
27
-
28
- def humanized_input
29
- window.name
25
+ _('Resolve Hosts for %s') % window.name
30
26
  end
31
27
 
32
28
  end
@@ -2,8 +2,6 @@ module ForemanPatch
2
2
  class Invocation < ::ApplicationRecord
3
3
  include ForemanTasks::Concerns::ActionSubject
4
4
 
5
- STATUSES = %w(planned pending running success warning error cancelled)
6
-
7
5
  belongs_to :round, class_name: 'ForemanPatch::Round', inverse_of: :invocations
8
6
  has_one :window, through: :round
9
7
  has_one :cycle, through: :window
@@ -12,8 +10,6 @@ module ForemanPatch
12
10
 
13
11
  belongs_to :task, class_name: 'ForemanTasks::Task'
14
12
 
15
- has_many :events, class_name: 'ForemanPatch::Events'
16
-
17
13
  scope :planned, -> { where(status: 'planned') }
18
14
  scope :pending, -> { where(status: 'pending') }
19
15
  scope :running, -> { where(status: 'running') }
@@ -34,6 +30,10 @@ module ForemanPatch
34
30
  task&.main_action&.planned_actions || []
35
31
  end
36
32
 
33
+ def events
34
+ task&.main_action&.live_output || []
35
+ end
36
+
37
37
  def complete?
38
38
  ['success', 'warning', 'failed', 'cancelled'].include? status
39
39
  end
@@ -2,8 +2,6 @@ module ForemanPatch
2
2
  class Round < ::ApplicationRecord
3
3
  include ForemanTasks::Concerns::ActionSubject
4
4
 
5
- STATUSES = %w(planned pending running complete).freeze
6
-
7
5
  belongs_to :window, class_name: 'ForemanPatch::Window'
8
6
  has_one :cycle, class_name: 'ForemanPatch::Cycle', through: :window
9
7
  belongs_to :group, class_name: 'ForemanPatch::Group'
@@ -34,8 +32,29 @@ module ForemanPatch
34
32
  scoped_search on: :name, complete_value: true
35
33
  scoped_search on: :status, complete_value: true
36
34
 
37
- def progress
38
- ForemanPatch::Invocation::STATUSES.product([0]).to_h.merge(invocations.unscope(:order).group(:status).count)
35
+ def progress(total = nil, done = nil)
36
+ if invocations.empty? || done == 0
37
+ 0
38
+ else
39
+ total ||= invocations.count
40
+ done ||= sub_tasks.where(result: %w(success warning error)).count
41
+ ((done.to_f / total) * 100).round
42
+ end
43
+ end
44
+
45
+ def progress_report
46
+ invocations.reduce({
47
+ pending: 0,
48
+ running: 0,
49
+ success: 0,
50
+ warning: 0,
51
+ failed: 0,
52
+ cancelled: 0,
53
+ }) do |report, invocation|
54
+ status = (invocation.status == 'planned' ? 'pending' : invocation.status)
55
+ report[status.to_sym] += 1
56
+ report
57
+ end
39
58
  end
40
59
 
41
60
  def finished?