foreman_rh_cloud 13.0.7 → 13.0.9

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/foreman_rh_cloud/registration_manager_extensions.rb +39 -0
  3. data/app/controllers/foreman_inventory_upload/accounts_controller.rb +1 -1
  4. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +1 -1
  5. data/lib/foreman_inventory_upload/async/create_missing_insights_facets.rb +3 -2
  6. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +1 -23
  7. data/lib/foreman_inventory_upload/async/upload_report_direct_job.rb +200 -0
  8. data/lib/foreman_inventory_upload.rb +6 -6
  9. data/lib/foreman_rh_cloud/engine.rb +1 -0
  10. data/lib/foreman_rh_cloud/plugin.rb +4 -0
  11. data/lib/foreman_rh_cloud/version.rb +1 -1
  12. data/lib/inventory_sync/async/inventory_hosts_sync.rb +0 -2
  13. data/lib/tasks/rh_cloud_inventory.rake +11 -1
  14. data/package.json +1 -1
  15. data/test/controllers/accounts_controller_test.rb +1 -1
  16. data/test/controllers/uploads_controller_test.rb +1 -1
  17. data/test/jobs/cloud_connector_announce_task_test.rb +3 -2
  18. data/test/jobs/connector_playbook_execution_reporter_task_test.rb +32 -20
  19. data/test/jobs/create_missing_insights_facets_test.rb +151 -0
  20. data/test/jobs/exponential_backoff_test.rb +9 -8
  21. data/test/jobs/generate_host_report_test.rb +100 -0
  22. data/test/jobs/generate_report_job_test.rb +146 -0
  23. data/test/jobs/host_inventory_report_job_test.rb +244 -0
  24. data/test/jobs/insights_client_status_aging_test.rb +3 -2
  25. data/test/jobs/insights_full_sync_test.rb +13 -7
  26. data/test/jobs/insights_resolutions_sync_test.rb +9 -5
  27. data/test/jobs/insights_rules_sync_test.rb +5 -3
  28. data/test/jobs/inventory_full_sync_test.rb +9 -5
  29. data/test/jobs/inventory_hosts_sync_test.rb +11 -6
  30. data/test/jobs/inventory_scheduled_sync_test.rb +10 -6
  31. data/test/jobs/inventory_self_host_sync_test.rb +1 -1
  32. data/test/jobs/queue_for_upload_job_test.rb +10 -19
  33. data/test/jobs/remove_insights_hosts_job_test.rb +14 -15
  34. data/test/jobs/single_host_report_job_test.rb +155 -0
  35. data/test/jobs/upload_report_direct_job_test.rb +399 -0
  36. data/test/unit/lib/foreman_rh_cloud/registration_manager_extensions_test.rb +192 -0
  37. data/webpack/ForemanColumnExtensions/index.js +2 -0
  38. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js +1 -1
  39. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js +4 -5
  40. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +4 -2
  41. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +9 -10
  42. data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +4 -1
  43. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +24 -17
  44. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +178 -8
  45. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +3 -1
  46. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +69 -51
  47. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +3 -3
  48. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +3 -9
  49. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +12 -7
  50. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +2 -2
  51. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +3 -3
  52. data/webpack/InsightsCloudSync/InsightsCloudSync.js +3 -3
  53. data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +10 -0
  54. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +1 -1
  55. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +5 -5
  56. data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +2 -2
  57. data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +77 -22
  58. data/webpack/common/Hooks/ConfigHooks.js +3 -16
  59. metadata +17 -8
  60. data/lib/foreman_inventory_upload/async/upload_report_job.rb +0 -97
  61. data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +0 -55
  62. data/test/jobs/upload_report_job_test.rb +0 -37
  63. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +0 -36
  64. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +0 -112
  65. data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f148316b7ac917b1933b533d2843cf30eb8f0a7da25ff4ef2c7783d2b423ba5
4
- data.tar.gz: e04853a27fb4bea875dfab45068cf2ee6ba683e41b4a25c83e17b812b80d4f2a
3
+ metadata.gz: 9d818ad6b4142546fe8d3b8c0e54f49600ed30915f6b22f142bc1861938c5dba
4
+ data.tar.gz: 3d0e310b2cf587243c64623713af21e164c87e87e21a5edeee556f16613ae8fc
5
5
  SHA512:
6
- metadata.gz: eb7d02b868a7e7f78c589c46bd6b0816450ac73b8e45f3b882ab9b30ab62ea21d0cdb69a1f1d2ac465fe8d1b2bdebaaed2555a78b240e77625ce9744b0756853
7
- data.tar.gz: c361ab887cbd84cbe912f7bf23c36d40b69239f31cf26d369a35cd3d88b2d163e9e485b185aadb105692da044b658674da73f41fd21017ba75f7440cb6509588
6
+ metadata.gz: ae35c83c6c45af99a891a3ff243d10f7f7616891facecab5f6afa34287f2282eb3c0175680537bb0a17b62352ea42b43d1e1d4365a517f6086c3e1d82fbd725b
7
+ data.tar.gz: f9e14d6356e65f5649b3c4a2f57ef381539aa296e12fbbe7c0e5fcc28c47e855bd9ad8e1ab3a9ca739319b9c9882e41de9d578244be2f1fcbd83ca8d1c4160de
@@ -0,0 +1,39 @@
1
+ module ForemanRhCloud
2
+ module RegistrationManagerExtensions
3
+ include ForemanRhCloud::CertAuth
4
+
5
+ def logger
6
+ Rails.logger
7
+ end
8
+
9
+ def unregister_host(host, options = {})
10
+ organization_destroy = options.fetch(:organization_destroy, false)
11
+
12
+ # Reload to ensure we have fresh association data
13
+ host.reload
14
+
15
+ # Only delete from HBI in IoP mode (hosted mode uses async job for cleanup)
16
+ hbi_host_destroy(host) if ForemanRhCloud.with_iop_smart_proxy? && !organization_destroy && host.insights_facet&.uuid&.presence
17
+ host.insights&.destroy!
18
+ super(host, options)
19
+ end
20
+
21
+ def hbi_host_destroy(host)
22
+ uuid = host.insights_facet.uuid
23
+ logger.debug "Unregistering host #{uuid} from HBI"
24
+ execute_cloud_request(
25
+ organization: host.organization,
26
+ method: :delete,
27
+ url: ForemanInventoryUpload.host_by_id_url(uuid),
28
+ headers: {
29
+ content_type: :json,
30
+ }
31
+ )
32
+ rescue RestClient::NotFound
33
+ Rails.logger.warn(_("Attempted to destroy HBI host %s, but host does not exist in HBI") % uuid)
34
+ rescue StandardError => e
35
+ # TODO: Improve error handling - don't break registration if HBI delete fails
36
+ Rails.logger.error(format(_("Failed to destroy HBI host %s: %s"), uuid, e.message))
37
+ end
38
+ end
39
+ end
@@ -7,7 +7,7 @@ module ForemanInventoryUpload
7
7
  accounts = Hash[
8
8
  labels.map do |id, label|
9
9
  generate_report_status = status_for(id, ForemanInventoryUpload::Async::GenerateReportJob)
10
- upload_report_status = status_for(id, ForemanInventoryUpload::Async::UploadReportJob)
10
+ upload_report_status = status_for(id, ForemanInventoryUpload::Async::UploadReportDirectJob)
11
11
  report_file_paths = ForemanInventoryUpload.report_file_paths(id)
12
12
 
13
13
  [
@@ -6,7 +6,7 @@ module ForemanInventoryUpload
6
6
  before_action :require_non_iop_smart_proxy, only: [:enable_cloud_connector]
7
7
 
8
8
  def last
9
- label = ForemanInventoryUpload::Async::UploadReportJob.output_label(params[:organization_id])
9
+ label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(params[:organization_id])
10
10
  output = ForemanInventoryUpload::Async::ProgressOutput.get(label)&.full_output
11
11
 
12
12
  render json: {
@@ -8,7 +8,7 @@ module ForemanInventoryUpload
8
8
  def run
9
9
  organization = ::Organization.find(input[:organization_id])
10
10
  hosts_without_facets = ::ForemanInventoryUpload::Generators::Queries.for_org(organization, hosts_query: 'null? insights_uuid')
11
- facet_count = hosts_without_facets.count
11
+ facet_count = 0
12
12
  hosts_without_facets.each do |batch|
13
13
  facets = batch.pluck(:id, 'katello_subscription_facets.uuid').map do |host_id, uuid|
14
14
  {
@@ -20,9 +20,10 @@ module ForemanInventoryUpload
20
20
  # rubocop:disable Rails/SkipsModelValidations
21
21
  InsightsFacet.upsert_all(facets, unique_by: :host_id) unless facets.empty?
22
22
  # rubocop:enable Rails/SkipsModelValidations
23
+ facet_count += facets.size
23
24
  end
24
25
  output[:result] = facet_count.zero? ? _("There were no missing Insights facets") : format(_("Missing Insights facets created: %s"), facet_count)
25
- Rails.logger.info output[:result]
26
+ Rails.logger.debug output[:result]
26
27
  end
27
28
  end
28
29
  end
@@ -9,7 +9,6 @@ module ForemanInventoryUpload
9
9
  def run
10
10
  logger.debug('Ensuring objects')
11
11
  ensure_ouput_folder
12
- ensure_output_script
13
12
  logger.debug("Copying #{report_file} to #{uploads_folder}")
14
13
  enqueued_file_name = File.join(uploads_folder, report_file)
15
14
  FileUtils.mv(File.join(base_folder, report_file), enqueued_file_name)
@@ -22,31 +21,10 @@ module ForemanInventoryUpload
22
21
  @uploads_folder ||= ForemanInventoryUpload.uploads_folder
23
22
  end
24
23
 
25
- def script_file
26
- @script_file ||= File.join(uploads_folder, ForemanInventoryUpload.upload_script_file)
27
- end
28
-
29
24
  def ensure_ouput_folder
30
25
  FileUtils.mkdir_p(uploads_folder)
31
26
  end
32
27
 
33
- def ensure_output_script
34
- return if File.exist?(script_file)
35
-
36
- script_source = File.join(ForemanRhCloud::Engine.root, 'lib/foreman_inventory_upload/scripts/uploader.sh.erb')
37
-
38
- template_src = Foreman::Renderer::Source::String.new(content: File.read(script_source))
39
- scope = Foreman::Renderer::Scope::Base.new(
40
- source: template_src,
41
- variables: {
42
- upload_url: ForemanInventoryUpload.upload_url,
43
- }
44
- )
45
- script_source = Foreman::Renderer.render(template_src, scope)
46
- File.write(script_file, script_source)
47
- FileUtils.chmod('+x', script_file)
48
- end
49
-
50
28
  def logger
51
29
  Foreman::Logging.logger('background')
52
30
  end
@@ -60,7 +38,7 @@ module ForemanInventoryUpload
60
38
  end
61
39
 
62
40
  def plan_upload_report(enqueued_file_name, organization_id)
63
- plan_action(UploadReportJob, enqueued_file_name, organization_id)
41
+ plan_action(UploadReportDirectJob, enqueued_file_name, organization_id)
64
42
  end
65
43
  end
66
44
  end
@@ -0,0 +1,200 @@
1
+ require 'tempfile'
2
+ require 'rest-client'
3
+
4
+ module ForemanInventoryUpload
5
+ module Async
6
+ class UploadReportDirectJob < ::Actions::EntryAction
7
+ include AsyncHelpers
8
+ include ::ForemanRhCloud::Async::ExponentialBackoff
9
+ include ::ForemanRhCloud::CloudRequest
10
+
11
+ # Wrapper class to avoid monkey-patching File for multipart uploads
12
+ class FileUpload
13
+ attr_reader :file, :content_type
14
+
15
+ def initialize(file, content_type:)
16
+ @file = file
17
+ @content_type = content_type
18
+ end
19
+
20
+ def read(*args)
21
+ @file.read(*args)
22
+ end
23
+
24
+ def path
25
+ @file.path
26
+ end
27
+
28
+ def respond_to_missing?(method_name, include_private = false)
29
+ @file.respond_to?(method_name, include_private) || super
30
+ end
31
+
32
+ def method_missing(method_name, *args, &block)
33
+ if @file.respond_to?(method_name)
34
+ @file.send(method_name, *args, &block)
35
+ else
36
+ super
37
+ end
38
+ end
39
+ end
40
+
41
+ def self.output_label(label)
42
+ "upload_for_#{label}"
43
+ end
44
+
45
+ def plan(filename, organization_id)
46
+ # NOTE: This implementation assumes a single organization will not trigger multiple
47
+ # concurrent uploads. The instance_label is derived from organization_id alone, which
48
+ # means concurrent uploads for the same org would share ProgressOutput storage.
49
+ # This matches the pattern in GenerateReportJob. A full fix for thread-safety
50
+ # requires UI changes to display multiple concurrent tasks per org (tracked for PR #2).
51
+ label = UploadReportDirectJob.output_label(organization_id)
52
+ clear_task_output(label)
53
+ plan_self(
54
+ instance_label: label,
55
+ filename: filename,
56
+ organization_id: organization_id
57
+ )
58
+ end
59
+
60
+ def try_execute
61
+ if content_disconnected?
62
+ progress_output do |progress_output|
63
+ progress_output.write_line("Report was not moved and upload was canceled because connection to Insights is not enabled. Report location: #{filename}.")
64
+ progress_output.status = "Task aborted, exit 1"
65
+ done!
66
+ end
67
+ return
68
+ end
69
+
70
+ unless organization.owner_details&.dig('upstreamConsumer', 'idCert')
71
+ logger.info("Skipping organization '#{organization}', no candlepin certificate defined.")
72
+ progress_output do |progress_output|
73
+ progress_output.write_line("Skipping organization #{organization}, no candlepin certificate defined.")
74
+ progress_output.status = "Task aborted, exit 1"
75
+ done!
76
+ end
77
+ return
78
+ end
79
+
80
+ Tempfile.create([organization.name, '.pem']) do |cer_file|
81
+ cer_file.write(certificate[:cert])
82
+ cer_file.write(certificate[:key])
83
+ cer_file.flush
84
+ upload_report(cer_file.path)
85
+ end
86
+
87
+ done!
88
+ end
89
+
90
+ def upload_report(cer_path)
91
+ progress_output do |progress_output|
92
+ progress_output.write_line("Uploading report for organization #{organization.label}...")
93
+ progress_output.status = "Running upload"
94
+
95
+ begin
96
+ upload_file(cer_path)
97
+ progress_output.write_line("Upload completed successfully")
98
+ move_to_done_folder
99
+ progress_output.write_line("Uploaded file moved to done/ folder")
100
+ progress_output.status = "pid #{Process.pid} exit 0"
101
+ rescue StandardError => e
102
+ progress_output.write_line("Upload failed: #{e.message}")
103
+ progress_output.status = "pid #{Process.pid} exit 1"
104
+ raise
105
+ end
106
+ end
107
+ end
108
+
109
+ def upload_file(cer_path)
110
+ cert_content = File.read(cer_path)
111
+
112
+ File.open(filename, 'rb') do |file|
113
+ # Wrap file with FileUpload class for RestClient multipart handling
114
+ # RestClient requires objects with :read, :path, and :content_type methods
115
+ wrapped_file = FileUpload.new(file, content_type: 'application/vnd.redhat.qpc.tar+tgz')
116
+
117
+ response = execute_cloud_request(
118
+ method: :post,
119
+ url: ForemanInventoryUpload.upload_url,
120
+ payload: {
121
+ multipart: true,
122
+ file: wrapped_file,
123
+ },
124
+ headers: {
125
+ 'X-Org-Id' => organization.label,
126
+ },
127
+ ssl_client_cert: OpenSSL::X509::Certificate.new(cert_content),
128
+ ssl_client_key: OpenSSL::PKey::RSA.new(cert_content),
129
+ timeout: 600,
130
+ open_timeout: 60
131
+ )
132
+
133
+ logger.debug("Upload response code: #{response.code}")
134
+ end
135
+ end
136
+
137
+ def move_to_done_folder
138
+ FileUtils.mkdir_p(ForemanInventoryUpload.done_folder)
139
+ done_file = ForemanInventoryUpload.done_file_path(File.basename(filename))
140
+ FileUtils.mv(filename, done_file)
141
+ logger.debug("Moved #{filename} to #{done_file}")
142
+ end
143
+
144
+ def certificate
145
+ ForemanRhCloud.with_iop_smart_proxy? ? foreman_certificate : manifest_certificate
146
+ end
147
+
148
+ def manifest_certificate
149
+ candlepin_id_certificate = organization.owner_details['upstreamConsumer']['idCert']
150
+ {
151
+ cert: candlepin_id_certificate['cert'],
152
+ key: candlepin_id_certificate['key'],
153
+ }
154
+ end
155
+
156
+ def foreman_certificate
157
+ {
158
+ cert: File.read(Setting[:ssl_certificate]),
159
+ key: File.read(Setting[:ssl_priv_key]),
160
+ }
161
+ end
162
+
163
+ def filename
164
+ input[:filename]
165
+ end
166
+
167
+ def organization
168
+ Organization.find(input[:organization_id])
169
+ end
170
+
171
+ def content_disconnected?
172
+ !Setting[:subscription_connection_enabled]
173
+ end
174
+
175
+ def progress_output
176
+ progress_output = ProgressOutput.register(instance_label)
177
+ yield(progress_output)
178
+ ensure
179
+ progress_output.close
180
+ end
181
+
182
+ def instance_label
183
+ input[:instance_label]
184
+ end
185
+
186
+ def logger
187
+ Foreman::Logging.logger('background')
188
+ end
189
+
190
+ def rescue_strategy_for_self
191
+ Dynflow::Action::Rescue::Fail
192
+ end
193
+
194
+ def clear_task_output(label)
195
+ TaskOutputLine.where(label: label).delete_all
196
+ TaskOutputStatus.where(label: label).delete_all
197
+ end
198
+ end
199
+ end
200
+ end
@@ -48,10 +48,6 @@ module ForemanInventoryUpload
48
48
  @outputs_folder ||= ensure_folder(File.join(ForemanInventoryUpload.base_folder, 'outputs/'))
49
49
  end
50
50
 
51
- def self.upload_script_file
52
- 'uploader.sh'
53
- end
54
-
55
51
  def self.facts_archive_name(organization, filter = nil)
56
52
  "report_for_#{organization}#{filter.empty? ? nil : "[#{filter.to_s.parameterize}]"}.tar.xz"
57
53
  end
@@ -88,8 +84,12 @@ module ForemanInventoryUpload
88
84
  inventory_base_url + "?hostname_or_id=#{ForemanRhCloud.foreman_host.fqdn}"
89
85
  end
90
86
 
91
- def self.hosts_by_ids_url(host_ids)
92
- host_ids_string = host_ids.join(',')
87
+ def self.host_by_id_url(host_uuid)
88
+ "#{inventory_base_url}/#{host_uuid}"
89
+ end
90
+
91
+ def self.hosts_by_ids_url(host_uuids)
92
+ host_ids_string = host_uuids.join(',')
93
93
  "#{inventory_base_url}/#{host_ids_string}"
94
94
  end
95
95
  end
@@ -40,6 +40,7 @@ module ForemanRhCloud
40
40
  ::Host::Managed.include RhCloudHost
41
41
 
42
42
  ::Katello::Api::Rhsm::CandlepinDynflowProxyController.include InsightsCloud::PackageProfileUploadExtensions
43
+ ::Katello::RegistrationManager.singleton_class.prepend ::ForemanRhCloud::RegistrationManagerExtensions
43
44
  end
44
45
  end
45
46
 
@@ -146,6 +146,10 @@ module ForemanRhCloud
146
146
  end
147
147
  end
148
148
 
149
+ ::Foreman::Plugin.app_metadata_registry.register(:foreman_rh_cloud, {
150
+ iop: ForemanRhCloud.with_iop_smart_proxy?,
151
+ })
152
+
149
153
  extend_template_helpers ForemanRhCloud::TemplateRendererHelper
150
154
  allowed_template_helpers :remediations_playbook, :download_rh_playbook
151
155
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '13.0.7'.freeze
2
+ VERSION = '13.0.9'.freeze
3
3
  end
@@ -8,8 +8,6 @@ module InventorySync
8
8
  set_callback :step, :around, :create_missing_hosts
9
9
 
10
10
  def plan(organizations)
11
- # Do not run for local advisor, since we use sub-man id to identify hosts.
12
- return if ForemanRhCloud.with_iop_smart_proxy?
13
11
  # by default the tasks will be executed concurrently
14
12
  super(organizations)
15
13
  plan_self_host_sync
@@ -39,13 +39,23 @@ namespace :rh_cloud_inventory do
39
39
 
40
40
  User.as_anonymous_admin do
41
41
  organization_ids.each do |organization_id|
42
- ForemanTasks.sync_task(
42
+ task = ForemanTasks.sync_task(
43
43
  ForemanInventoryUpload::Async::HostInventoryReportJob,
44
44
  base_folder,
45
45
  organization_id,
46
46
  filter,
47
47
  false # don't upload; the user ran report:generate and not report:generate_upload
48
48
  )
49
+
50
+ if task.result == 'success'
51
+ unless Setting[:subscription_connection_enabled]
52
+ target_file = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(organization_id, filter))
53
+ puts "Generated #{target_file} for organization id #{organization_id}"
54
+ end
55
+ else
56
+ puts "Failed to generate report for organization id #{organization_id}. Task result: #{task.result}"
57
+ puts "Check task #{task.id} in the Tasks dashboard for error details."
58
+ end
49
59
  end
50
60
  puts "Check the Uploading tab for report uploading status." if Setting[:subscription_connection_enabled]
51
61
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "13.0.7",
3
+ "version": "13.0.9",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,7 +11,7 @@ class AccountsControllerTest < ActionController::TestCase
11
11
  generate_label = ForemanInventoryUpload::Async::GenerateReportJob.output_label(test_org.id)
12
12
  generate_output = ForemanInventoryUpload::Async::ProgressOutput.register(generate_label)
13
13
  generate_output.status = 'generate_status_test'
14
- upload_label = ForemanInventoryUpload::Async::UploadReportJob.output_label(test_org.id)
14
+ upload_label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(test_org.id)
15
15
  upload_output = ForemanInventoryUpload::Async::ProgressOutput.register(upload_label)
16
16
  upload_output.status = 'upload_status_test'
17
17
 
@@ -8,7 +8,7 @@ class UploadsControllerTest < ActionController::TestCase
8
8
  test_org = FactoryBot.create(:organization)
9
9
  ForemanInventoryUpload::Async::ProgressOutput
10
10
  .expects(:get)
11
- .with(ForemanInventoryUpload::Async::UploadReportJob.output_label(test_org.id))
11
+ .with(ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(test_org.id))
12
12
  .returns(progress_output)
13
13
  progress_output.expects(:full_output).returns('test output')
14
14
 
@@ -4,7 +4,7 @@ require 'foreman_tasks/test_helpers'
4
4
  require "#{ForemanTasks::Engine.root}/test/support/dummy_dynflow_action"
5
5
 
6
6
  class CloudConnectorAnnounceTaskTest < ActiveSupport::TestCase
7
- include ForemanTasks::TestHelpers::WithInThreadExecutor
7
+ include Dynflow::Testing::Factories
8
8
 
9
9
  setup do
10
10
  RemoteExecutionFeature.register(
@@ -23,7 +23,8 @@ class CloudConnectorAnnounceTaskTest < ActiveSupport::TestCase
23
23
  test 'It executes cloud presence announcer' do
24
24
  ForemanRhCloud::CloudPresence.any_instance.expects(:announce_to_sources).times(Organization.unscoped.count)
25
25
 
26
- ForemanTasks.sync_task(InsightsCloud::Async::CloudConnectorAnnounceTask, @job_invocation)
26
+ action = create_and_plan_action(InsightsCloud::Async::CloudConnectorAnnounceTask, @job_invocation)
27
+ finalize_action(action)
27
28
  end
28
29
 
29
30
  private
@@ -4,7 +4,7 @@ require 'foreman_tasks/test_helpers'
4
4
  require "#{ForemanTasks::Engine.root}/test/support/dummy_dynflow_action"
5
5
 
6
6
  class ConnectorPlaybookExecutionReporterTaskTest < ActiveSupport::TestCase
7
- include ForemanTasks::TestHelpers::WithInThreadExecutor
7
+ include Dynflow::Testing::Factories
8
8
 
9
9
  # override default send behavior for the test
10
10
  class TestConnectorPlaybookExecutionReporterTask < InsightsCloud::Async::ConnectorPlaybookExecutionReporterTask
@@ -35,17 +35,19 @@ class ConnectorPlaybookExecutionReporterTaskTest < ActiveSupport::TestCase
35
35
 
36
36
  TestConnectorPlaybookExecutionReporterTask.any_instance.stubs(:job_finished?).returns(true)
37
37
 
38
- actual = ForemanTasks.sync_task(TestConnectorPlaybookExecutionReporterTask, @job_invocation)
38
+ action = create_and_plan_action(TestConnectorPlaybookExecutionReporterTask, @job_invocation)
39
+ action = run_action(action)
39
40
 
40
- actual_report = actual.output[:saved_reports].first.to_s
41
+ saved_reports = action.output[:saved_reports]
42
+ actual_report = saved_reports.first.to_s
41
43
 
42
- assert_equal 1, actual.output[:saved_reports].size
44
+ assert_equal 1, saved_reports.size
43
45
  assert_not_nil actual_report
44
46
  actual_jsonl = read_jsonl(actual_report)
45
47
 
46
- assert_equal true, actual.output['task']['invocation_status']['task_state']['task_done_reported']
47
- assert_equal 0, actual.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
48
- assert_equal 0, actual.output['task']['invocation_status']['hosts_state']['TEST_UUID2']['exit_status']
48
+ assert_equal true, action.output['task']['invocation_status']['task_state']['task_done_reported']
49
+ assert_equal 0, action.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
50
+ assert_equal 0, action.output['task']['invocation_status']['hosts_state']['TEST_UUID2']['exit_status']
49
51
 
50
52
  assert_equal true, @job_invocation.finished?
51
53
  assert_equal 'stopped', @job_invocation.sub_task_for_host(Host.where(name: 'host1').first)['state']
@@ -77,20 +79,25 @@ class ConnectorPlaybookExecutionReporterTaskTest < ActiveSupport::TestCase
77
79
 
78
80
  ArrangeTestHost.any_instance.stubs(:job_finished?).returns(false, true)
79
81
 
80
- actual = ForemanTasks.sync_task(ArrangeTestHost, @job_invocation)
82
+ action = create_and_plan_action(ArrangeTestHost, @job_invocation)
83
+ action = run_action(action)
81
84
 
82
- actual_report1 = actual.output[:saved_reports].first.to_s
83
- actual_report2 = actual.output[:saved_reports].second.to_s
85
+ # Process polling cycles - manually trigger Poll events until done
86
+ action = run_action(action, Dynflow::Action::Polling::Poll) until action.done?
84
87
 
85
- assert_equal 2, actual.output[:saved_reports].size
88
+ saved_reports = action.output[:saved_reports]
89
+ actual_report1 = saved_reports.first.to_s
90
+ actual_report2 = saved_reports.second.to_s
91
+
92
+ assert_equal 2, saved_reports.size
86
93
  assert_not_nil actual_report1
87
94
  assert_not_nil actual_report2
88
95
 
89
96
  actual_json1 = read_jsonl(actual_report1)
90
97
  actual_json2 = read_jsonl(actual_report2)
91
98
 
92
- assert_equal true, actual.output['task']['invocation_status']['task_state']['task_done_reported']
93
- assert_equal 0, actual.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
99
+ assert_equal true, action.output['task']['invocation_status']['task_state']['task_done_reported']
100
+ assert_equal 0, action.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
94
101
 
95
102
  assert_equal 'stopped', @job_invocation.sub_task_for_host(Host.where(name: 'host1').first)['state']
96
103
 
@@ -141,13 +148,18 @@ class ConnectorPlaybookExecutionReporterTaskTest < ActiveSupport::TestCase
141
148
 
142
149
  ArrangeTestHostTwo.any_instance.stubs(:job_finished?).returns(false, false, true)
143
150
 
144
- actual = ForemanTasks.sync_task(ArrangeTestHostTwo, @job_invocation)
151
+ action = create_and_plan_action(ArrangeTestHostTwo, @job_invocation)
152
+ action = run_action(action)
153
+
154
+ # Process polling cycles - manually trigger Poll events until done
155
+ action = run_action(action, Dynflow::Action::Polling::Poll) until action.done?
145
156
 
146
- actual_report1 = actual.output[:saved_reports].first.to_s
147
- actual_report2 = actual.output[:saved_reports].second.to_s
148
- actual_report3 = actual.output[:saved_reports].third.to_s
157
+ saved_reports = action.output[:saved_reports]
158
+ actual_report1 = saved_reports.first.to_s
159
+ actual_report2 = saved_reports.second.to_s
160
+ actual_report3 = saved_reports.third.to_s
149
161
 
150
- assert_equal 3, actual.output[:saved_reports].size
162
+ assert_equal 3, saved_reports.size
151
163
  assert_not_nil actual_report1
152
164
  assert_not_nil actual_report2
153
165
  assert_not_nil actual_report3
@@ -156,8 +168,8 @@ class ConnectorPlaybookExecutionReporterTaskTest < ActiveSupport::TestCase
156
168
  actual_json2 = read_jsonl(actual_report2)
157
169
  actual_json3 = read_jsonl(actual_report3)
158
170
 
159
- assert_equal true, actual.output['task']['invocation_status']['task_state']['task_done_reported']
160
- assert_equal 0, actual.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
171
+ assert_equal true, action.output['task']['invocation_status']['task_state']['task_done_reported']
172
+ assert_equal 0, action.output['task']['invocation_status']['hosts_state']['TEST_UUID1']['exit_status']
161
173
 
162
174
  assert_not_nil actual_report_updated = actual_json1.find { |l| l['type'] == 'playbook_run_update' && l['host'] == 'TEST_UUID1' }
163
175
  assert_equal 'TEST_CORRELATION', actual_report_updated['correlation_id']