foreman_rh_cloud 4.0.21.1 → 4.0.22

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/foreman_rh_cloud/cloud_auth.rb +12 -0
  3. data/app/services/foreman_rh_cloud/cloud_request.rb +14 -0
  4. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +1 -6
  5. data/app/services/foreman_rh_cloud/remediations_retriever.rb +1 -4
  6. data/lib/foreman_inventory_upload/generators/fact_helpers.rb +19 -0
  7. data/lib/foreman_inventory_upload/generators/slice.rb +5 -5
  8. data/lib/foreman_rh_cloud/version.rb +1 -1
  9. data/lib/insights_cloud/async/insights_full_sync.rb +4 -14
  10. data/lib/insights_cloud/async/insights_resolutions_sync.rb +1 -4
  11. data/lib/insights_cloud/async/insights_rules_sync.rb +2 -7
  12. data/lib/inventory_sync/async/inventory_full_sync.rb +2 -1
  13. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +8 -0
  14. data/lib/inventory_sync/async/query_inventory_job.rb +1 -4
  15. data/lib/tasks/rh_cloud_inventory.rake +6 -0
  16. data/package.json +1 -1
  17. data/test/factories/inventory_upload_factories.rb +1 -1
  18. data/test/test_plugin_helper.rb +0 -1
  19. data/test/unit/slice_generator_test.rb +55 -27
  20. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonActions.js +28 -63
  21. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/integrations.test.js.snap +2 -3
  22. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableActions.js +19 -19
  23. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableActions.test.js.snap +14 -14
  24. data/webpack/InsightsCloudSync/InsightsCloudSync.js +4 -1
  25. data/webpack/InsightsCloudSync/InsightsCloudSyncActions.js +44 -20
  26. data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +2 -0
  27. data/webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncActions.test.js.snap +11 -7
  28. data/webpack/common/ForemanTasks/ForemanTasksActions.js +64 -0
  29. data/webpack/common/ForemanTasks/ForemanTasksHelpers.js +7 -0
  30. data/webpack/common/ForemanTasks/index.js +1 -0
  31. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97882071192995f2da93032050b9ecdfa616dba407c8d032bfd29f6741ea9d56
4
- data.tar.gz: 88bca49cea9ee2abac2d2dc9d608a33329ad9e214d57035424e8e24984691537
3
+ metadata.gz: ea5629e755a80131b35cb1509ff5d44fefccbe70c0362829e7d7c0f1d9f2484d
4
+ data.tar.gz: b1e1ded88509739b56711a97aa81797592d5b4ec8b32cb811ad9d6a280adfb57
5
5
  SHA512:
6
- metadata.gz: 67dd2ada55ac862b2d57ddf893e7408d002c40c2f89a141e6bf8c115d6eeee32d19b156e7668751f591665f948fa04d628719e5f6f5ab9e4609c02f0a14a93f4
7
- data.tar.gz: 54ded7bb163e4a38cd3fa4a62dfe101484b98e87c016514b985190f77a07c7556e980dd8574dc5fb70cacb3fcc521a37a1f4f2325e5360cdbb2ddd6f38816804
6
+ metadata.gz: 1ac6593a54fd506e2a8bb690bc4c6e046f92fea706333c77a54f9472b4977fd88201e2d13852f15418e326cee9961b25f31ef9cfda4703cc88f29c84d63a6459
7
+ data.tar.gz: '02649cb1f8b0e11d6570988f3cafe55e82d14bad6f133f5cf691c396b542156e0e2c2e132d0eb38a11bb421d14e5d31757e630ba463052cd4cbf71c701564fc7'
@@ -2,6 +2,8 @@ module ForemanRhCloud
2
2
  module CloudAuth
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ include CloudRequest
6
+
5
7
  def rh_credentials
6
8
  @rh_credentials ||= query_refresh_token
7
9
  end
@@ -24,5 +26,15 @@ module ForemanRhCloud
24
26
  Foreman::Logging.exception('Unable to authenticate using rh_cloud_token setting', e)
25
27
  raise ::Foreman::WrappedException.new(e, N_('Unable to authenticate using rh_cloud_token setting'))
26
28
  end
29
+
30
+ def execute_cloud_request(params)
31
+ final_params = {
32
+ headers: {
33
+ Authorization: "Bearer #{rh_credentials}",
34
+ },
35
+ }.deep_merge(params)
36
+
37
+ super(final_params)
38
+ end
27
39
  end
28
40
  end
@@ -0,0 +1,14 @@
1
+ module ForemanRhCloud
2
+ module CloudRequest
3
+ extend ActiveSupport::Concern
4
+
5
+ def execute_cloud_request(params)
6
+ final_params = {
7
+ verify_ssl: ForemanRhCloud.verify_ssl_method,
8
+ proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
9
+ }.deep_merge(params)
10
+
11
+ RestClient::Request.execute(final_params)
12
+ end
13
+ end
14
+ end
@@ -2,7 +2,7 @@ require 'rest-client'
2
2
 
3
3
  module ForemanRhCloud
4
4
  class CloudRequestForwarder
5
- include ::ForemanRhCloud::CloudAuth
5
+ include ForemanRhCloud::CloudRequest
6
6
 
7
7
  def forward_request(original_request, controller_name, branch_id, certs)
8
8
  forward_params = prepare_forward_params(original_request, branch_id)
@@ -22,7 +22,6 @@ module ForemanRhCloud
22
22
  def prepare_request_opts(original_request, forward_payload, forward_params, certs)
23
23
  base_params = {
24
24
  method: original_request.method,
25
- verify_ssl: ForemanRhCloud.verify_ssl_method,
26
25
  payload: forward_payload,
27
26
  headers: {
28
27
  params: forward_params,
@@ -33,10 +32,6 @@ module ForemanRhCloud
33
32
  base_params.merge(path_params(original_request.path, certs))
34
33
  end
35
34
 
36
- def execute_cloud_request(request_opts)
37
- RestClient::Request.execute request_opts
38
- end
39
-
40
35
  def prepare_forward_payload(original_request, controller_name)
41
36
  forward_payload = original_request.request_parameters[controller_name]
42
37
 
@@ -62,14 +62,11 @@ module ForemanRhCloud
62
62
  end
63
63
 
64
64
  def query_playbook
65
- RestClient::Request.execute(
65
+ execute_cloud_request(
66
66
  method: :post,
67
67
  url: InsightsCloud.playbook_url,
68
- verify_ssl: ForemanRhCloud.verify_ssl_method,
69
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
70
68
  headers: {
71
69
  content_type: :json,
72
- Authorization: "Bearer #{rh_credentials}",
73
70
  },
74
71
  payload: playbook_request.to_json
75
72
  )
@@ -10,6 +10,8 @@ module ForemanInventoryUpload
10
10
  CLOUD_AZURE = 'azure'
11
11
  CLOUD_ALIBABA = 'alibaba'
12
12
 
13
+ UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
14
+
13
15
  def fact_value(host, fact_name)
14
16
  value_record = host.fact_values.find do |fact_value|
15
17
  fact_value.fact_name_id == ForemanInventoryUpload::Generators::Queries.fact_names[fact_name]
@@ -104,6 +106,23 @@ module ForemanInventoryUpload
104
106
  def obfuscate_ip(ip, ips_dict)
105
107
  "10.230.230.#{ips_dict.count + 1}"
106
108
  end
109
+
110
+ def bios_uuid(host)
111
+ value = fact_value(host, 'dmi::system::uuid') || ''
112
+ uuid_value(value)
113
+ end
114
+
115
+ def uuid_value(value)
116
+ uuid_match = UUID_REGEX.match(value)
117
+ uuid_match&.to_s
118
+ end
119
+
120
+ def uuid_value!(value)
121
+ uuid = uuid_value(value)
122
+ raise Foreman::Exception.new(N_('Value %{value} is not a valid UUID') % {value: value}) if value && uuid.empty?
123
+
124
+ uuid
125
+ end
107
126
  end
108
127
  end
109
128
  end
@@ -25,7 +25,7 @@ module ForemanInventoryUpload
25
25
 
26
26
  def report_slice(hosts_batch)
27
27
  @stream.object do
28
- @stream.simple_field('report_slice_id', @slice_id)
28
+ @stream.simple_field('report_slice_id', uuid_value!(@slice_id))
29
29
  @stream.array_field('hosts', :last) do
30
30
  first = true
31
31
  hosts_batch.each do |host|
@@ -45,10 +45,10 @@ module ForemanInventoryUpload
45
45
  @stream.object do
46
46
  @stream.simple_field('fqdn', fqdn(host))
47
47
  @stream.simple_field('account', account_id(host.organization).to_s)
48
- @stream.simple_field('subscription_manager_id', host.subscription_facet&.uuid)
49
- @stream.simple_field('satellite_id', host.subscription_facet&.uuid)
50
- @stream.simple_field('bios_uuid', fact_value(host, 'dmi::system::uuid'))
51
- @stream.simple_field('vm_uuid', fact_value(host, 'virt::uuid'))
48
+ @stream.simple_field('subscription_manager_id', uuid_value!(host.subscription_facet&.uuid))
49
+ @stream.simple_field('satellite_id', uuid_value!(host.subscription_facet&.uuid))
50
+ @stream.simple_field('bios_uuid', bios_uuid(host))
51
+ @stream.simple_field('vm_uuid', uuid_value(fact_value(host, 'virt::uuid')))
52
52
  report_ip_addresses(host, host_ips_cache)
53
53
  report_mac_addresses(host)
54
54
  @stream.object_field('system_profile') do
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '4.0.21.1'.freeze
2
+ VERSION = '4.0.22'.freeze
3
3
  end
@@ -50,28 +50,18 @@ module InsightsCloud
50
50
  end
51
51
 
52
52
  def query_insights_hits
53
- hits_response = RestClient::Request.execute(
53
+ hits_response = execute_cloud_request(
54
54
  method: :get,
55
- url: InsightsCloud.hits_export_url,
56
- verify_ssl: ForemanRhCloud.verify_ssl_method,
57
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
58
- headers: {
59
- Authorization: "Bearer #{rh_credentials}",
60
- }
55
+ url: InsightsCloud.hits_export_url
61
56
  )
62
57
 
63
58
  JSON.parse(hits_response)
64
59
  end
65
60
 
66
61
  def query_insights_rules
67
- rules_response = RestClient::Request.execute(
62
+ rules_response = execute_cloud_request(
68
63
  method: :get,
69
- url: InsightsCloud.rules_url,
70
- verify_ssl: ForemanRhCloud.verify_ssl_method,
71
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
72
- headers: {
73
- Authorization: "Bearer #{rh_credentials}",
74
- }
64
+ url: InsightsCloud.rules_url
75
65
  )
76
66
 
77
67
  JSON.parse(rules_response)
@@ -22,14 +22,11 @@ module InsightsCloud
22
22
  private
23
23
 
24
24
  def query_insights_resolutions(rule_ids)
25
- resolutions_response = RestClient::Request.execute(
25
+ resolutions_response = execute_cloud_request(
26
26
  method: :post,
27
27
  url: InsightsCloud.resolutions_url,
28
- verify_ssl: ForemanRhCloud.verify_ssl_method,
29
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
30
28
  headers: {
31
29
  content_type: :json,
32
- Authorization: "Bearer #{rh_credentials}",
33
30
  },
34
31
  payload: {
35
32
  issues: rule_ids,
@@ -37,14 +37,9 @@ module InsightsCloud
37
37
  private
38
38
 
39
39
  def query_insights_rules(offset)
40
- rules_response = RestClient::Request.execute(
40
+ rules_response = execute_cloud_request(
41
41
  method: :get,
42
- url: InsightsCloud.rules_url(offset: offset),
43
- verify_ssl: ForemanRhCloud.verify_ssl_method,
44
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
45
- headers: {
46
- Authorization: "Bearer #{rh_credentials}",
47
- }
42
+ url: InsightsCloud.rules_url(offset: offset)
48
43
  )
49
44
 
50
45
  JSON.parse(rules_response)
@@ -24,6 +24,7 @@ module InventorySync
24
24
 
25
25
  logger.debug("Synced hosts amount: #{host_statuses[:sync]}")
26
26
  logger.debug("Disconnected hosts amount: #{host_statuses[:disconnect]}")
27
+ output[:host_statuses] = host_statuses
27
28
  end
28
29
 
29
30
  def update_statuses_batch
@@ -53,7 +54,7 @@ module InventorySync
53
54
  end
54
55
 
55
56
  def host_statuses
56
- output[:host_statuses] ||= {
57
+ @host_statuses ||= {
57
58
  sync: 0,
58
59
  disconnect: 0,
59
60
  }
@@ -4,6 +4,14 @@ module InventorySync
4
4
  include ::Actions::RecurringAction
5
5
 
6
6
  def plan
7
+ unless Setting[:allow_auto_inventory_upload]
8
+ logger.debug(
9
+ 'The scheduled process is disabled due to the "allow_auto_inventory_upload"
10
+ setting being set to false.'
11
+ )
12
+ return
13
+ end
14
+
7
15
  Organization.unscoped.each do |org|
8
16
  plan_org_sync(org)
9
17
  end
@@ -29,13 +29,10 @@ module InventorySync
29
29
  private
30
30
 
31
31
  def query_inventory(page = 1)
32
- hosts_inventory_response = RestClient::Request.execute(
32
+ hosts_inventory_response = execute_cloud_request(
33
33
  method: :get,
34
34
  url: ForemanInventoryUpload.inventory_export_url,
35
- verify_ssl: ForemanRhCloud.verify_ssl_method,
36
- proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
37
35
  headers: {
38
- Authorization: "Bearer #{rh_credentials}",
39
36
  params: {
40
37
  per_page: 100,
41
38
  page: page,
@@ -23,6 +23,12 @@ namespace :rh_cloud_inventory do
23
23
  organizations = [ENV['organization_id']]
24
24
  base_folder = ENV['target'] || Dir.pwd
25
25
 
26
+ unless File.writable?(base_folder)
27
+ puts "#{base_folder} is not writable by the current process"
28
+ base_folder = Dir.mktmpdir
29
+ puts "Using #{base_folder} for the output"
30
+ end
31
+
26
32
  unless portal_user || organizations.empty?
27
33
  puts "Must specify either portal_user or organization_id"
28
34
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "4.0.21.1",
3
+ "version": "4.0.22",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -49,7 +49,7 @@ end
49
49
 
50
50
  FactoryBot.define do
51
51
  factory :katello_subscription_facets, :aliases => [:subscription_facet], :class => ::Katello::Host::SubscriptionFacet do
52
- sequence(:uuid) { |n| "uuid-#{n}-#{rand(500)}" }
52
+ sequence(:uuid) { |n| "00000000-%<n>04d-%<r>04d-0000-000000000000" % {n: n, r: rand(500)} }
53
53
  facts { { 'memory.memtotal' => "12 GB" } }
54
54
  end
55
55
  end
@@ -33,7 +33,6 @@ module KatelloLocationFix
33
33
  FactoryBot.create(:setting, name: 'default_location_subscribed_hosts')
34
34
  FactoryBot.create(:setting, name: 'default_location_puppet_content')
35
35
  Setting[:default_location_subscribed_hosts] = Location.first.title
36
- Setting[:default_location_puppet_content] = Location.first.title
37
36
  end
38
37
  end
39
38
  end
@@ -71,7 +71,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
71
71
  json_str = generator.render
72
72
  actual = JSON.parse(json_str.join("\n"))
73
73
 
74
- assert_equal 'slice_123', actual['report_slice_id']
74
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
75
75
  assert_not_nil(actual_host = actual['hosts'].first)
76
76
  assert_nil actual_host['ip_addresses']
77
77
  assert_nil actual_host['mac_addresses']
@@ -102,7 +102,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
102
102
  json_str = generator.render
103
103
  actual = JSON.parse(json_str.join("\n"))
104
104
 
105
- assert_equal 'slice_123', actual['report_slice_id']
105
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
106
106
  assert_not_nil(actual_host = actual['hosts'].first)
107
107
  assert_not_nil(actual_system_profile = actual_host['system_profile'])
108
108
  assert_equal 4, actual_system_profile['number_of_cpus']
@@ -120,7 +120,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
120
120
  json_str = generator.render
121
121
  actual = JSON.parse(json_str.join("\n"))
122
122
 
123
- assert_equal 'slice_123', actual['report_slice_id']
123
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
124
124
  assert_not_nil(actual_host = actual['hosts'].first)
125
125
  assert_equal @host.interfaces.where.not(ip: nil).first.ip, actual_host['ip_addresses'].first
126
126
  assert_equal @host.interfaces.where.not(mac: nil).first.mac, actual_host['mac_addresses'].first
@@ -142,7 +142,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
142
142
  json_str = generator.render
143
143
  actual = JSON.parse(json_str.join("\n"))
144
144
 
145
- assert_equal 'slice_123', actual['report_slice_id']
145
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
146
146
  assert_not_nil(actual_host = actual['hosts'].first)
147
147
  assert_equal @host.interfaces.where.not(ip: nil).first.ip, actual_host['ip_addresses'].first
148
148
  assert_equal @host.interfaces.where.not(mac: nil).first.mac, actual_host['mac_addresses'].first
@@ -172,7 +172,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
172
172
  json_str = generator.render
173
173
  actual = JSON.parse(json_str.join("\n"))
174
174
 
175
- assert_equal 'slice_123', actual['report_slice_id']
175
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
176
176
  assert_not_nil(actual_host = actual['hosts'].first)
177
177
  assert_equal @host.interfaces.where.not(ip: nil).first.ip, actual_host['ip_addresses'].first
178
178
  assert_equal @host.interfaces.where.not(mac: nil).first.mac, actual_host['mac_addresses'].first
@@ -191,7 +191,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
191
191
  json_str = generator.render
192
192
  actual = JSON.parse(json_str.join("\n"))
193
193
 
194
- assert_equal 'slice_123', actual['report_slice_id']
194
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
195
195
  assert_not_nil(actual_host = actual['hosts'].first)
196
196
  assert_equal '10.230.230.1', actual_host['ip_addresses'].first
197
197
  assert_not_nil(actual_system_profile = actual_host['system_profile'])
@@ -221,7 +221,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
221
221
  json_str = generator.render
222
222
  actual = JSON.parse(json_str.join("\n"))
223
223
 
224
- assert_equal 'slice_123', actual['report_slice_id']
224
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
225
225
  assert_not_nil(actual_host = actual['hosts'].first)
226
226
  assert_equal '10.230.230.100', actual_host['ip_addresses'].first
227
227
  assert_not_nil(actual_system_profile = actual_host['system_profile'])
@@ -243,7 +243,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
243
243
  json_str = generator.render
244
244
  actual = JSON.parse(json_str.join("\n"))
245
245
 
246
- assert_equal 'slice_123', actual['report_slice_id']
246
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
247
247
  assert_not_nil(actual_host = actual['hosts'].first)
248
248
  assert_equal 'obfuscated_name', actual_host['fqdn']
249
249
  assert_equal '1234', actual_host['account']
@@ -263,7 +263,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
263
263
 
264
264
  obfuscated_fqdn = Digest::SHA1.hexdigest(@host.fqdn) + '.example.com'
265
265
 
266
- assert_equal 'slice_123', actual['report_slice_id']
266
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
267
267
  assert_not_nil(actual_host = actual['hosts'].first)
268
268
  assert_equal obfuscated_fqdn, actual_host['fqdn']
269
269
  assert_equal '1234', actual_host['account']
@@ -282,7 +282,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
282
282
  json_str = generator.render
283
283
  actual = JSON.parse(json_str.join("\n"))
284
284
 
285
- assert_equal 'slice_123', actual['report_slice_id']
285
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
286
286
  assert_not_nil(actual_host = actual['hosts'].first)
287
287
  assert_equal @host.fqdn, actual_host['fqdn']
288
288
  assert_equal '1234', actual_host['account']
@@ -355,7 +355,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
355
355
  json_str = generator.render
356
356
  actual = JSON.parse(json_str.join("\n"))
357
357
 
358
- assert_equal 'slice_123', actual['report_slice_id']
358
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
359
359
  assert_not_nil(actual_host = actual['hosts'].first)
360
360
  assert_equal @host.fqdn, actual_host['fqdn']
361
361
  assert_not_nil(host_facts = actual_host['facts']&.first)
@@ -377,7 +377,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
377
377
  json_str = generator.render
378
378
  actual = JSON.parse(json_str.join("\n"))
379
379
 
380
- assert_equal 'slice_123', actual['report_slice_id']
380
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
381
381
  assert_not_nil(actual_host = actual['hosts'].first)
382
382
  assert_equal @host.fqdn, actual_host['fqdn']
383
383
  assert_not_nil(host_facts = actual_host['facts']&.first)
@@ -397,7 +397,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
397
397
  json_str = generator.render
398
398
  actual = JSON.parse(json_str.join("\n"))
399
399
 
400
- assert_equal 'slice_123', actual['report_slice_id']
400
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
401
401
  assert_not_nil(actual_host = actual['hosts'].first)
402
402
  assert_equal @host.fqdn, actual_host['fqdn']
403
403
  assert_equal '1234', actual_host['account']
@@ -417,7 +417,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
417
417
  json_str = generator.render
418
418
  actual = JSON.parse(json_str.join("\n"))
419
419
 
420
- assert_equal 'slice_123', actual['report_slice_id']
420
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
421
421
  assert_not_nil(actual_host = actual['hosts'].first)
422
422
  assert_equal @host.fqdn, actual_host['fqdn']
423
423
  assert_equal '1234', actual_host['account']
@@ -436,7 +436,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
436
436
  json_str = generator.render
437
437
  actual = JSON.parse(json_str.join("\n"))
438
438
 
439
- assert_equal 'slice_123', actual['report_slice_id']
439
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
440
440
  assert_equal 1, generator.hosts_count
441
441
  end
442
442
 
@@ -449,7 +449,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
449
449
  json_str = generator.render
450
450
  actual = JSON.parse(json_str.join("\n"))
451
451
 
452
- assert_equal 'slice_123', actual['report_slice_id']
452
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
453
453
  assert_not_nil(actual_host = actual['hosts'].first)
454
454
  assert_not_nil(actual_profile = actual_host['system_profile'])
455
455
  assert_equal 1024, actual_profile['system_memory_bytes']
@@ -475,7 +475,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
475
475
  json_str = generator.render
476
476
  actual = JSON.parse(json_str.join("\n"))
477
477
 
478
- assert_equal 'slice_123', actual['report_slice_id']
478
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
479
479
  assert_not_nil(actual_host = actual['hosts'].first)
480
480
  assert_not_nil(actual_host['account'])
481
481
  assert_not_empty(actual_host['account'])
@@ -492,7 +492,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
492
492
  json_str = generator.render
493
493
  actual = JSON.parse(json_str.join("\n"))
494
494
 
495
- assert_equal 'slice_123', actual['report_slice_id']
495
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
496
496
  assert_not_nil(actual_host = actual['hosts'].first)
497
497
  assert_not_nil(actual_profile = actual_host['system_profile'])
498
498
  assert_equal 'Red Hat Test Linux 7.1 (TestId)', actual_profile['os_release']
@@ -507,7 +507,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
507
507
  json_str = generator.render
508
508
  actual = JSON.parse(json_str.join("\n"))
509
509
 
510
- assert_equal 'slice_123', actual['report_slice_id']
510
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
511
511
  assert_not_nil(actual_host = actual['hosts'].first)
512
512
  assert_not_nil(actual_profile = actual_host['system_profile'])
513
513
  assert_equal 'virtual', actual_profile['infrastructure_type']
@@ -522,7 +522,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
522
522
  json_str = generator.render
523
523
  actual = JSON.parse(json_str.join("\n"))
524
524
 
525
- assert_equal 'slice_123', actual['report_slice_id']
525
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
526
526
  assert_not_nil(actual_host = actual['hosts'].first)
527
527
  assert_not_nil(actual_profile = actual_host['system_profile'])
528
528
  assert_equal 'physical', actual_profile['infrastructure_type']
@@ -537,7 +537,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
537
537
  json_str = generator.render
538
538
  actual = JSON.parse(json_str.join("\n"))
539
539
 
540
- assert_equal 'slice_123', actual['report_slice_id']
540
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
541
541
  assert_not_nil(actual_host = actual['hosts'].first)
542
542
  assert_not_nil(actual_profile = actual_host['system_profile'])
543
543
  assert_equal 'aws', actual_profile['cloud_provider']
@@ -552,7 +552,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
552
552
  json_str = generator.render
553
553
  actual = JSON.parse(json_str.join("\n"))
554
554
 
555
- assert_equal 'slice_123', actual['report_slice_id']
555
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
556
556
  assert_not_nil(actual_host = actual['hosts'].first)
557
557
  assert_not_nil(actual_profile = actual_host['system_profile'])
558
558
  assert_equal 'google', actual_profile['cloud_provider']
@@ -567,7 +567,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
567
567
  json_str = generator.render
568
568
  actual = JSON.parse(json_str.join("\n"))
569
569
 
570
- assert_equal 'slice_123', actual['report_slice_id']
570
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
571
571
  assert_not_nil(actual_host = actual['hosts'].first)
572
572
  assert_not_nil(actual_profile = actual_host['system_profile'])
573
573
  assert_equal 'azure', actual_profile['cloud_provider']
@@ -582,7 +582,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
582
582
  json_str = generator.render
583
583
  actual = JSON.parse(json_str.join("\n"))
584
584
 
585
- assert_equal 'slice_123', actual['report_slice_id']
585
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
586
586
  assert_not_nil(actual_host = actual['hosts'].first)
587
587
  assert_not_nil(actual_profile = actual_host['system_profile'])
588
588
  assert_equal 'alibaba', actual_profile['cloud_provider']
@@ -597,7 +597,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
597
597
  json_str = generator.render
598
598
  actual = JSON.parse(json_str.join("\n"))
599
599
 
600
- assert_equal 'slice_123', actual['report_slice_id']
600
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
601
601
  assert_not_nil(actual_host = actual['hosts'].first)
602
602
  assert_not_nil(actual_profile = actual_host['system_profile'])
603
603
  assert_equal 'alibaba', actual_profile['cloud_provider']
@@ -623,15 +623,43 @@ class SliceGeneratorTest < ActiveSupport::TestCase
623
623
  json_str = generator.render
624
624
  actual = JSON.parse(json_str.join("\n"))
625
625
 
626
- assert_equal 'slice_123', actual['report_slice_id']
626
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
627
627
  assert_not_nil(actual_host = actual['hosts'].first)
628
628
  assert_not_nil(actual_profile = actual_host['system_profile'])
629
629
  assert_not_nil(actual_profile['installed_packages'])
630
630
  end
631
631
 
632
+ test 'omits malformed bios_uuid field' do
633
+ FactoryBot.create(:fact_value, fact_name: fact_names['dmi::system::uuid'], value: 'test value', host: @host)
634
+
635
+ batch = Host.where(id: @host.id).in_batches.first
636
+ generator = create_generator(batch)
637
+
638
+ json_str = generator.render
639
+ actual = JSON.parse(json_str.join("\n"))
640
+
641
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
642
+ assert_not_nil(actual_host = actual['hosts'].first)
643
+ assert_nil actual_host['bios_uuid']
644
+ end
645
+
646
+ test 'passes valid bios_uuid field' do
647
+ FactoryBot.create(:fact_value, fact_name: fact_names['dmi::system::uuid'], value: 'D30B0B42-7824-2635-C62D-491394DE43F7', host: @host)
648
+
649
+ batch = Host.where(id: @host.id).in_batches.first
650
+ generator = create_generator(batch)
651
+
652
+ json_str = generator.render
653
+ actual = JSON.parse(json_str.join("\n"))
654
+
655
+ assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
656
+ assert_not_nil(actual_host = actual['hosts'].first)
657
+ assert_not_nil actual_host['bios_uuid']
658
+ end
659
+
632
660
  private
633
661
 
634
- def create_generator(batch, name = 'slice_123')
662
+ def create_generator(batch, name = '00000000-0000-0000-0000-000000000000')
635
663
  generator = ForemanInventoryUpload::Generators::Slice.new(batch, [], name)
636
664
  if block_given?
637
665
  yield(generator)
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import { get, post } from 'foremanReact/redux/API';
3
- import { withInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
2
+ import { post } from 'foremanReact/redux/API';
4
3
  import { addToast } from 'foremanReact/redux/actions/toasts';
5
4
  import { translate as __ } from 'foremanReact/common/I18n';
6
5
  import { inventoryUrl } from '../../../../ForemanInventoryHelpers';
@@ -9,7 +8,10 @@ import {
9
8
  INVENTORY_SYNC,
10
9
  INVENTORY_SYNC_TASK_UPDATE,
11
10
  } from './SyncButtonConstants';
12
- import { foremanUrl } from '../../../../../ForemanRhCloudHelpers';
11
+ import {
12
+ setupTaskPolling,
13
+ taskRelatedToast,
14
+ } from '../../../../../common/ForemanTasks';
13
15
 
14
16
  export const handleSync = () => dispatch => {
15
17
  dispatch(
@@ -21,9 +23,9 @@ export const handleSync = () => dispatch => {
21
23
  task: { id },
22
24
  },
23
25
  }) => {
24
- dispatch(getSyncTaskInterval(id));
26
+ dispatch(setupInventorySyncTaskPolling(id, dispatch));
25
27
  return dispatch(
26
- taskPageRefererToast(id, 'info', __('Inventory sync has started:'))
28
+ taskRelatedToast(id, 'info', __('Inventory sync has started:'))
27
29
  );
28
30
  },
29
31
  errorToast: inventorySyncErrorToast,
@@ -31,62 +33,25 @@ export const handleSync = () => dispatch => {
31
33
  );
32
34
  };
33
35
 
34
- export const getSyncTaskInterval = id => dispatch => {
35
- dispatch(
36
- withInterval(
37
- get({
38
- key: INVENTORY_SYNC_TASK_UPDATE,
39
- url: inventoryUrl(`tasks/${id}`),
40
- handleSuccess: ({ data: { result, output } }, stopTaskInterval) => {
41
- if (result === 'success') {
42
- const {
43
- host_statuses: { sync, disconnect },
44
- } = output;
45
- dispatch(
46
- addToast({
47
- sticky: true,
48
- type: 'success',
49
- message: (
50
- <Toast syncHosts={sync} disconnectHosts={disconnect} />
51
- ),
52
- })
53
- );
54
- }
55
- if (result === 'error') {
56
- dispatch(
57
- taskPageRefererToast(
58
- id,
59
- 'error',
60
- __('Inventory sync has failed:'),
61
- true
62
- )
63
- );
64
- }
65
- stopTaskInterval();
66
- },
67
- errorToast: inventorySyncErrorToast,
68
- })
69
- )
70
- );
71
- };
72
-
73
- const inventorySyncErrorToast = ({ message, response }) =>
74
- `${__('Inventory sync has failed: ')} ${response.data?.message || message}`;
75
-
76
- const taskPageRefererToast = (taskID, toastType, prefix, sticky = false) =>
77
- addToast({
78
- sticky,
79
- type: toastType,
80
- message: (
81
- <span>
82
- {prefix}{' '}
83
- <a
84
- target="_blank"
85
- rel="noopener noreferrer"
86
- href={foremanUrl(`/foreman_tasks/tasks/${taskID}`)}
87
- >
88
- {__('view the task page for more details')}
89
- </a>
90
- </span>
91
- ),
36
+ export const setupInventorySyncTaskPolling = (id, dispatch) =>
37
+ setupTaskPolling({
38
+ taskId: id,
39
+ key: INVENTORY_SYNC_TASK_UPDATE,
40
+ onTaskSuccess: ({
41
+ output: {
42
+ host_statuses: { sync, disconnect },
43
+ },
44
+ }) =>
45
+ dispatch(
46
+ addToast({
47
+ sticky: true,
48
+ type: 'success',
49
+ message: <Toast syncHosts={sync} disconnectHosts={disconnect} />,
50
+ })
51
+ ),
52
+ dispatch,
92
53
  });
54
+
55
+ const inventorySyncErrorToast = message =>
56
+ `${__('Inventory sync has failed: ')} ${message.response?.data?.message ||
57
+ message}`;
@@ -22,7 +22,7 @@ Array [
22
22
  "errorToast": [Function],
23
23
  "interval": 3000,
24
24
  "type": "API_GET",
25
- "url": "/foreman_inventory_upload/tasks/1",
25
+ "url": "/foreman_tasks/api/tasks/1/details?include_permissions",
26
26
  },
27
27
  ],
28
28
  Array [
@@ -31,7 +31,7 @@ Array [
31
31
  "message": Object {
32
32
  "message": <span>
33
33
  Inventory sync has started:
34
-
34
+ <br />
35
35
  <a
36
36
  href="/foreman_tasks/tasks/1"
37
37
  rel="noopener noreferrer"
@@ -40,7 +40,6 @@ Array [
40
40
  view the task page for more details
41
41
  </a>
42
42
  </span>,
43
- "sticky": false,
44
43
  "type": "info",
45
44
  },
46
45
  },
@@ -19,25 +19,6 @@ export const fetchInsights = (queryParams = {}) => (dispatch, getState) => {
19
19
  ...queryParams,
20
20
  };
21
21
 
22
- dispatch(
23
- get({
24
- key: INSIGHTS_HITS_API_KEY,
25
- url: INSIGHTS_HITS_PATH,
26
- params: {
27
- page,
28
- per_page: perPage,
29
- search: query,
30
- order: `${sortBy} ${sortOrder}`,
31
- },
32
- handleSuccess: response => {
33
- if (isSelectAll) {
34
- selectAllIds(dispatch, response.data.hits || []);
35
- dispatch(selectAll());
36
- }
37
- },
38
- })
39
- );
40
-
41
22
  const uri = new URI();
42
23
  uri.search({
43
24
  page,
@@ -58,6 +39,25 @@ export const fetchInsights = (queryParams = {}) => (dispatch, getState) => {
58
39
  if (!isSelectAll) {
59
40
  dispatch(setSelectAllAlert(false));
60
41
  }
42
+
43
+ return dispatch(
44
+ get({
45
+ key: INSIGHTS_HITS_API_KEY,
46
+ url: INSIGHTS_HITS_PATH,
47
+ params: {
48
+ page,
49
+ per_page: perPage,
50
+ search: query,
51
+ order: `${sortBy} ${sortOrder}`,
52
+ },
53
+ handleSuccess: response => {
54
+ if (isSelectAll) {
55
+ selectAllIds(dispatch, response.data.hits || []);
56
+ dispatch(selectAll());
57
+ }
58
+ },
59
+ })
60
+ );
61
61
  };
62
62
 
63
63
  const selectAllIds = (dispatch, results, prevSelectedIds = {}) => {
@@ -26,6 +26,20 @@ Array [
26
26
 
27
27
  exports[`insights table actions should fetchInsights 1`] = `
28
28
  Array [
29
+ Array [
30
+ Object {
31
+ "payload": Object {
32
+ "args": Array [
33
+ Object {
34
+ "pathname": "/foreman_rh_cloud/insights_cloud",
35
+ "search": "?page=2&per_page=7&search=&sort_by=&sort_order=&select_all=true",
36
+ },
37
+ ],
38
+ "method": "push",
39
+ },
40
+ "type": "@@router/CALL_HISTORY_METHOD",
41
+ },
42
+ ],
29
43
  Array [
30
44
  Object {
31
45
  "payload": Object {
@@ -61,20 +75,6 @@ Array [
61
75
  "url": "/insights_cloud/hits",
62
76
  },
63
77
  ],
64
- Array [
65
- Object {
66
- "payload": Object {
67
- "args": Array [
68
- Object {
69
- "pathname": "/foreman_rh_cloud/insights_cloud",
70
- "search": "?page=2&per_page=7&search=&sort_by=&sort_order=&select_all=true",
71
- },
72
- ],
73
- "method": "push",
74
- },
75
- "type": "@@router/CALL_HISTORY_METHOD",
76
- },
77
- ],
78
78
  ]
79
79
  `;
80
80
 
@@ -36,7 +36,10 @@ const InsightsCloudSync = ({
36
36
  toolbarButtons={
37
37
  <>
38
38
  <RemediationModal />
39
- <Button variant="secondary" onClick={syncInsights}>
39
+ <Button
40
+ variant="secondary"
41
+ onClick={() => syncInsights(fetchInsights, query)}
42
+ >
40
43
  {__('Start recommendations sync')}
41
44
  </Button>
42
45
  </>
@@ -1,25 +1,49 @@
1
- import React from 'react';
2
1
  import { post } from 'foremanReact/redux/API';
3
2
  import { translate as __ } from 'foremanReact/common/I18n';
4
3
  import { insightsCloudUrl } from './InsightsCloudSyncHelpers';
5
- import { INSIGHTS_CLOUD_SYNC } from './InsightsCloudSyncConstants';
6
- import { foremanUrl } from '../ForemanRhCloudHelpers';
4
+ import {
5
+ INSIGHTS_CLOUD_SYNC,
6
+ INSIGHTS_CLOUD_SYNC_TASK,
7
+ } from './InsightsCloudSyncConstants';
8
+ import { setupTaskPolling, taskRelatedToast } from '../common/ForemanTasks';
7
9
 
8
- export const syncInsights = () =>
9
- post({
10
- key: INSIGHTS_CLOUD_SYNC,
11
- url: insightsCloudUrl('tasks'),
12
- successToast: response => (
13
- <span>
14
- {__('Recommendation sync has started: ')}
15
- <a
16
- target="_blank"
17
- rel="noopener noreferrer"
18
- href={foremanUrl(`/foreman_tasks/tasks/${response.data?.task?.id}`)}
19
- >
20
- {__('view the task in progress')}
21
- </a>
22
- </span>
23
- ),
24
- errorToast: error => `${__('Recommendation sync has failed: ')} ${error}`,
10
+ export const syncInsights = (fetchInsights, query) => dispatch =>
11
+ dispatch(
12
+ post({
13
+ key: INSIGHTS_CLOUD_SYNC,
14
+ url: insightsCloudUrl('tasks'),
15
+ handleSuccess: ({
16
+ data: {
17
+ task: { id },
18
+ },
19
+ }) => {
20
+ dispatch(syncInsightsStartedToast(id));
21
+ dispatch(setupInsightsTaskPolling(id, fetchInsights, query, dispatch));
22
+ },
23
+ errorToast: error => syncInsightsError(error),
24
+ })
25
+ );
26
+
27
+ const syncInsightsError = error =>
28
+ `${__('Recommendation sync has failed: ')} ${error}`;
29
+
30
+ const syncInsightsStartedToast = taskId =>
31
+ taskRelatedToast(taskId, 'info', __('Recommendation sync has started: '));
32
+
33
+ const setupInsightsTaskPolling = (taskId, fetchInsights, query, dispatch) =>
34
+ setupTaskPolling({
35
+ taskId,
36
+ key: INSIGHTS_CLOUD_SYNC_TASK,
37
+ onTaskSuccess: () => {
38
+ fetchInsights({ query, page: 1 });
39
+ dispatch(
40
+ taskRelatedToast(
41
+ taskId,
42
+ 'success',
43
+ __('Recommendations synced successfully')
44
+ )
45
+ );
46
+ },
47
+ taskErrorMessage: data => syncInsightsError(data.humanized.errors),
48
+ dispatch,
25
49
  });
@@ -4,6 +4,8 @@ import { foremanUrl } from '../ForemanRhCloudHelpers';
4
4
 
5
5
  export const INSIGHTS_CLOUD_SYNC = 'INSIGHTS_CLOUD_SYNC';
6
6
 
7
+ export const INSIGHTS_CLOUD_SYNC_TASK = 'INSIGHTS_CLOUD_SYNC_TASK';
8
+
7
9
  export const INSIGHTS_SYNC_PAGE_TITLE = __('Red Hat Insights');
8
10
 
9
11
  export const INSIGHTS_PATH = foremanUrl('/foreman_rh_cloud/insights_cloud');
@@ -1,11 +1,15 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`Insights cloud sync actions should syncInsights 1`] = `
4
- Object {
5
- "errorToast": [Function],
6
- "key": "INSIGHTS_CLOUD_SYNC",
7
- "successToast": [Function],
8
- "type": "post-some-type",
9
- "url": "/insights_cloud/tasks",
10
- }
4
+ Array [
5
+ Array [
6
+ Object {
7
+ "errorToast": [Function],
8
+ "handleSuccess": [Function],
9
+ "key": "INSIGHTS_CLOUD_SYNC",
10
+ "type": "post-some-type",
11
+ "url": "/insights_cloud/tasks",
12
+ },
13
+ ],
14
+ ]
11
15
  `;
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { get } from 'foremanReact/redux/API';
3
+ import { withInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
+ import { addToast } from 'foremanReact/redux/actions/toasts';
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+ import { foremanTaskDetailsUrl } from './ForemanTasksHelpers';
7
+ import { foremanUrl } from '../../ForemanRhCloudHelpers';
8
+
9
+ export const setupTaskPolling = ({
10
+ taskId,
11
+ key,
12
+ onTaskSuccess,
13
+ onTaskError,
14
+ taskErrorMessage,
15
+ dispatch,
16
+ }) =>
17
+ withInterval(
18
+ get({
19
+ key,
20
+ url: foremanTaskDetailsUrl(taskId),
21
+ handleSuccess: ({ data }, stopTaskInterval) => {
22
+ if (data.result === 'success') {
23
+ stopTaskInterval();
24
+ onTaskSuccess(data, dispatch);
25
+ }
26
+ if (data.result === 'error') {
27
+ stopTaskInterval();
28
+ if (taskErrorMessage === undefined) {
29
+ taskErrorMessage = errorData =>
30
+ `${__('The task failed with the following error:')} ${
31
+ errorData.humanized.errors
32
+ }`;
33
+ }
34
+ if (onTaskError === undefined) {
35
+ onTaskError = errorData =>
36
+ dispatch(defaultTaskErrorHandler(errorData, taskErrorMessage));
37
+ }
38
+ onTaskError(data, dispatch);
39
+ }
40
+ },
41
+ errorToast: error => `Could not get task details: ${error}`,
42
+ })
43
+ );
44
+
45
+ export const taskRelatedToast = (taskID, type, message) =>
46
+ addToast({
47
+ type,
48
+ message: (
49
+ <span>
50
+ {message}
51
+ <br />
52
+ <a
53
+ target="_blank"
54
+ rel="noopener noreferrer"
55
+ href={foremanUrl(`/foreman_tasks/tasks/${taskID}`)}
56
+ >
57
+ {__('view the task page for more details')}
58
+ </a>
59
+ </span>
60
+ ),
61
+ });
62
+
63
+ const defaultTaskErrorHandler = (data, taskErrorMessage) =>
64
+ taskRelatedToast(data.id, 'error', taskErrorMessage(data));
@@ -0,0 +1,7 @@
1
+ import { foremanUrl } from '../../ForemanRhCloudHelpers';
2
+
3
+ export const foremanTasksApiPath = path =>
4
+ foremanUrl(`/foreman_tasks/api/tasks/${path}`);
5
+
6
+ export const foremanTaskDetailsUrl = id =>
7
+ foremanTasksApiPath(`${id}/details?include_permissions`);
@@ -0,0 +1 @@
1
+ export { setupTaskPolling, taskRelatedToast } from './ForemanTasksActions';
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_rh_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.21.1
4
+ version: 4.0.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-06 00:00:00.000000000 Z
11
+ date: 2021-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katello
@@ -172,6 +172,7 @@ files:
172
172
  - app/services/foreman_rh_cloud/branch_info.rb
173
173
  - app/services/foreman_rh_cloud/cloud_auth.rb
174
174
  - app/services/foreman_rh_cloud/cloud_connector.rb
175
+ - app/services/foreman_rh_cloud/cloud_request.rb
175
176
  - app/services/foreman_rh_cloud/cloud_request_forwarder.rb
176
177
  - app/services/foreman_rh_cloud/remediations_retriever.rb
177
178
  - app/services/foreman_rh_cloud/template_renderer_helper.rb
@@ -620,6 +621,9 @@ files:
620
621
  - webpack/__tests__/__snapshots__/ForemanRhCloudHelpers.test.js.snap
621
622
  - webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap
622
623
  - webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap
624
+ - webpack/common/ForemanTasks/ForemanTasksActions.js
625
+ - webpack/common/ForemanTasks/ForemanTasksHelpers.js
626
+ - webpack/common/ForemanTasks/index.js
623
627
  - webpack/common/Switcher/HelpLabel.js
624
628
  - webpack/common/Switcher/SwitcherPF4.js
625
629
  - webpack/common/Switcher/SwitcherPF4.scss