foreman_rh_cloud 1.0.10 → 1.0.11
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.
- checksums.yaml +4 -4
- data/README.md +33 -0
- data/app/controllers/insights_cloud/hits_controller.rb +17 -0
- data/app/models/concerns/rh_cloud_host.rb +12 -0
- data/app/views/hosts/_insights_tab.html.erb +15 -0
- data/config/routes.rb +1 -0
- data/lib/foreman_inventory_upload/async/generate_report_job.rb +1 -1
- data/lib/foreman_inventory_upload/async/shell_process.rb +15 -9
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +19 -1
- data/lib/foreman_inventory_upload/generators/metadata.rb +3 -0
- data/lib/foreman_inventory_upload/generators/queries.rb +2 -4
- data/lib/foreman_rh_cloud/engine.rb +10 -0
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/tasks/insights.rake +15 -0
- data/lib/tasks/{generator.rake → rh_cloud_inventory.rake} +7 -1
- data/package.json +3 -1
- data/test/jobs/upload_report_job_test.rb +34 -0
- data/test/unit/metadata_generator_test.rb +2 -0
- data/test/unit/slice_generator_test.rb +17 -0
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +3 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/StatusChart/StatusChart.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/StatusChart/__tests__/__snapshots__/StatusChart.test.js.snap +1 -1
- data/webpack/ForemanInventoryUpload/Components/TabContainer/tabContainer.scss +1 -1
- data/webpack/ForemanRhCloudPages.js +2 -0
- data/webpack/ForemanRhCloudReducers.js +2 -0
- data/webpack/ForemanRhCloudSelectors.js +5 -0
- data/webpack/ForemanRhCloudTestHelpers.js +6 -1
- data/webpack/InsightsHostDetailsTab/InsightsTab.js +64 -0
- data/webpack/InsightsHostDetailsTab/InsightsTab.scss +86 -0
- data/webpack/InsightsHostDetailsTab/InsightsTabActions.js +30 -0
- data/webpack/InsightsHostDetailsTab/InsightsTabConstants.js +3 -0
- data/webpack/InsightsHostDetailsTab/InsightsTabReducer.js +26 -0
- data/webpack/InsightsHostDetailsTab/InsightsTabSelectors.js +3 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.fixtures.js +25 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js +13 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabActions.test.js +13 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabIntegration.test.js +17 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabReducer.test.js +35 -0
- data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabSelectors.test.js +13 -0
- data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTab.test.js.snap +30 -0
- data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabActions.test.js.snap +20 -0
- data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabReducer.test.js.snap +41 -0
- data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabSelectors.test.js.snap +20 -0
- data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +69 -0
- data/webpack/InsightsHostDetailsTab/components/ListItem/index.js +1 -0
- data/webpack/InsightsHostDetailsTab/index.js +20 -0
- data/webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap +1 -0
- data/webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap +3 -0
- data/webpack/stories/decorators/withCardsDecorator.js +1 -1
- metadata +38 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2b89191efb4cb97cec7c9e2a2d1cc41e255f02f7c04e95ecf7c1753e3b718ed
|
4
|
+
data.tar.gz: 38846a43180f47c4ebf888b8af0624a3edf460a10b0e3f02eca17bdd074f5142
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d1fd157774d8b4d2007ea0139b05c6d39a749d432f6e1bcdb3d5efa5f39480743e1220434037131ccf65486edcd1fde24de39ed165653aa074062131d957394
|
7
|
+
data.tar.gz: 531cc12e64d7a4f8957029f7d7517dd80d30758c9ba070dd2603c5e64f324d399484824cc160dca8bef53810fa44aaeaf77e92e6a2d6ffdeb1f634b316a2af6e
|
data/README.md
CHANGED
@@ -11,6 +11,39 @@ for how to install Foreman plugins
|
|
11
11
|
|
12
12
|
*Usage here*
|
13
13
|
|
14
|
+
### In Satellite
|
15
|
+
|
16
|
+
#### Inventory upload
|
17
|
+
|
18
|
+
In UI: Configure -> Inventory Upload -> Restart
|
19
|
+
|
20
|
+
From command-line:
|
21
|
+
|
22
|
+
export organization_id=1
|
23
|
+
export target=/var/lib/foreman/red_hat_inventory/generated_reports/
|
24
|
+
/usr/sbin/foreman-rake rh_cloud_inventory:report:generate
|
25
|
+
|
26
|
+
#### Fetch hosts remediation data
|
27
|
+
|
28
|
+
In UI: Configure -> Insights -> Sync now
|
29
|
+
|
30
|
+
From command-line:
|
31
|
+
|
32
|
+
/usr/sbin/foreman-rake rh_cloud_inventory:sync
|
33
|
+
|
34
|
+
#### Synchronize inventory status
|
35
|
+
|
36
|
+
In UI: Configure -> Inventory Upload -> Sync inventory status
|
37
|
+
|
38
|
+
From command-line:
|
39
|
+
|
40
|
+
# all organizations
|
41
|
+
/usr/sbin/foreman-rake rh_cloud_insights:sync
|
42
|
+
|
43
|
+
# specific organization with id 1
|
44
|
+
export organization_id=1
|
45
|
+
/usr/sbin/foreman-rake rh_cloud_insights:sync
|
46
|
+
|
14
47
|
## TODO
|
15
48
|
|
16
49
|
*Todo list here*
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module InsightsCloud
|
2
|
+
class HitsController < ::ApplicationController
|
3
|
+
def index
|
4
|
+
host = Host.where(id: host_id_param).first
|
5
|
+
|
6
|
+
render json: {
|
7
|
+
hits: host.insights.hits,
|
8
|
+
}, status: :ok
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def host_id_param
|
14
|
+
params.require(:host_id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module RhCloudHost
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
has_many(
|
6
|
+
:inventory_upload_facts,
|
7
|
+
-> { where(fact_name_id: ForemanInventoryUpload::Generators::Queries.fact_names.values) },
|
8
|
+
class_name: 'FactValue',
|
9
|
+
:foreign_key => :host_id
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% content_for(:javascripts) do %>
|
2
|
+
<%= webpacked_plugins_js_for :'foreman_rh_cloud' %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for(:stylesheets) do %>
|
6
|
+
<%= webpacked_plugins_css_for :'foreman_rh_cloud' %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<div id="host_details_insights_react_container"></div>
|
10
|
+
<%= mount_react_component(
|
11
|
+
'InsightsHostDetailsTab',
|
12
|
+
'#host_details_insights_react_container',
|
13
|
+
{ hostID: host.id }.to_json,
|
14
|
+
flatten_data: true
|
15
|
+
) %>
|
data/config/routes.rb
CHANGED
@@ -8,24 +8,30 @@ module ForemanInventoryUpload
|
|
8
8
|
def perform(instance_label)
|
9
9
|
klass_name = self.class.name
|
10
10
|
logger.debug("Starting #{klass_name} with label #{instance_label}")
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
progress_output_for(instance_label) do |progress_output|
|
12
|
+
Open3.popen2e(hash_to_s(env), command) do |_stdin, stdout_stderr, wait_thread|
|
13
|
+
progress_output.status = "Running in pid #{wait_thread.pid}"
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
stdout_stderr.each do |out_line|
|
16
|
+
progress_output.write_line(out_line)
|
17
|
+
end
|
18
18
|
|
19
|
-
|
19
|
+
progress_output.status = wait_thread.value.to_s
|
20
|
+
end
|
20
21
|
end
|
21
22
|
logger.debug("Finished job #{klass_name} with label #{instance_label}")
|
22
|
-
ensure
|
23
|
-
progress_output.close
|
24
23
|
end
|
25
24
|
|
26
25
|
def command
|
27
26
|
end
|
28
27
|
|
28
|
+
def progress_output_for(instance_label)
|
29
|
+
progress_output = ProgressOutput.register(instance_label)
|
30
|
+
yield(progress_output)
|
31
|
+
ensure
|
32
|
+
progress_output.close
|
33
|
+
end
|
34
|
+
|
29
35
|
def env
|
30
36
|
{}
|
31
37
|
end
|
@@ -8,15 +8,33 @@ module ForemanInventoryUpload
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def perform(filename, organization_id)
|
11
|
+
label = UploadReportJob.output_label(organization_id)
|
11
12
|
@filename = filename
|
12
13
|
@organization = Organization.find(organization_id)
|
13
14
|
|
15
|
+
if Setting[:content_disconnected]
|
16
|
+
progress_output_for(label) do |progress_output|
|
17
|
+
progress_output.write_line('Upload was stopped since disconnected mode setting is enabled for content on this instance.')
|
18
|
+
progress_output.status = "Task aborted, exit 1"
|
19
|
+
end
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
unless @organization.owner_details&.fetch('upstreamConsumer')&.fetch('idCert')
|
24
|
+
logger.info("Skipping organization '#{@organization}', no candlepin certificate defined.")
|
25
|
+
progress_output_for(label) do |progress_output|
|
26
|
+
progress_output.write_line("Skipping organization #{@organization}, no candlepin certificate defined.")
|
27
|
+
progress_output.status = "Task aborted, exit 1"
|
28
|
+
end
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
14
32
|
Tempfile.create([@organization.name, '.pem']) do |cer_file|
|
15
33
|
cer_file.write(rh_credentials[:cert])
|
16
34
|
cer_file.write(rh_credentials[:key])
|
17
35
|
cer_file.flush
|
18
36
|
@cer_path = cer_file.path
|
19
|
-
super(
|
37
|
+
super(label)
|
20
38
|
end
|
21
39
|
end
|
22
40
|
|
@@ -21,6 +21,9 @@ module ForemanInventoryUpload
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def render_report(metadata)
|
24
|
+
metadata ||= {}
|
25
|
+
metadata['foreman_rh_cloud_version'] = ForemanRhCloud::VERSION
|
26
|
+
|
24
27
|
@stream.object do
|
25
28
|
@stream.simple_field('report_id', Foreman.uuid)
|
26
29
|
@stream.simple_field('host_inventory_api_version', '1.0')
|
@@ -30,23 +30,21 @@ module ForemanInventoryUpload
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.for_slice(base)
|
33
|
-
fact_values = FactValue.where(fact_name_id: fact_names.values)
|
34
33
|
base
|
35
34
|
.joins(:subscription_facet)
|
36
|
-
.eager_load(:fact_values)
|
37
35
|
.preload(
|
38
36
|
:interfaces,
|
39
37
|
:installed_packages,
|
40
38
|
:content_facet,
|
41
39
|
:host_statuses,
|
40
|
+
:inventory_upload_facts,
|
42
41
|
subscription_facet: [:pools, :installed_products, :hypervisor_host]
|
43
42
|
)
|
44
|
-
.merge(fact_values)
|
45
43
|
end
|
46
44
|
|
47
45
|
def self.for_report(portal_user)
|
48
46
|
org_ids = organizations_for_user(portal_user).pluck(:id)
|
49
|
-
|
47
|
+
for_org(org_ids)
|
50
48
|
end
|
51
49
|
|
52
50
|
def self.for_org(organization_id)
|
@@ -66,9 +66,19 @@ module ForemanRhCloud
|
|
66
66
|
register_global_js_file 'subscriptions_extension'
|
67
67
|
|
68
68
|
register_custom_status(InventorySync::InventoryStatus)
|
69
|
+
|
70
|
+
extend_page 'hosts/show' do |context|
|
71
|
+
context.add_pagelet :main_tabs,
|
72
|
+
partial: 'hosts/insights_tab',
|
73
|
+
name: _('Insights'),
|
74
|
+
onlyif: proc { |host| host.insights }
|
75
|
+
end
|
69
76
|
end
|
70
77
|
|
71
78
|
::Katello::UINotifications::Subscriptions::ManifestImportSuccess.include ForemanInventoryUpload::Notifications::ManifestImportSuccessNotificationOverride if defined?(Katello)
|
79
|
+
|
80
|
+
::Host::Managed.include RhCloudHost
|
81
|
+
::Host::Base.include RhCloudHost
|
72
82
|
end
|
73
83
|
|
74
84
|
initializer "foreman_rh_cloud.set_dynflow.config.on_init", :before => :finisher_hook do |_app|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
namespace :rh_cloud_insights do
|
2
|
+
desc "Synchronize Insights inventory"
|
3
|
+
task sync: :environment do
|
4
|
+
if ! ENV['organization_id'].nil?
|
5
|
+
organizations = [ Organization.where(:id => ENV['organization_id']).first ]
|
6
|
+
else
|
7
|
+
organizations = Organization.all
|
8
|
+
end
|
9
|
+
|
10
|
+
organizations.each do |organization|
|
11
|
+
InventorySync::Async::InventoryFullSync.perform_now(organization)
|
12
|
+
puts "Synchronized inventory for organization '#{organization.name}'"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'tempfile'
|
2
2
|
|
3
|
-
namespace :
|
3
|
+
namespace :rh_cloud_inventory do
|
4
4
|
namespace :report do
|
5
5
|
desc 'Generate inventory report to be sent to Red Hat cloud'
|
6
6
|
task generate: :environment do
|
@@ -26,4 +26,10 @@ namespace :foreman_inventory_upload do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
desc "Synchronize Insights hosts hits"
|
31
|
+
task sync: :environment do
|
32
|
+
InsightsCloud::Async::InsightsFullSync.perform_now()
|
33
|
+
puts "Synchronized Insights hosts hits data"
|
34
|
+
end
|
29
35
|
end
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "foreman_rh_cloud",
|
3
|
-
"version": "
|
3
|
+
"version": "1.0.11",
|
4
4
|
"description": "Inventory Upload =============",
|
5
5
|
"main": "index.js",
|
6
6
|
"scripts": {
|
@@ -47,6 +47,8 @@
|
|
47
47
|
"eslint": "^4.10.0",
|
48
48
|
"eslint-import-resolver-babel-module": "^4.0.0",
|
49
49
|
"eslint-plugin-patternfly-react": "0.2.0",
|
50
|
+
"eslint-plugin-promise": "^4.2.1",
|
51
|
+
"eslint-plugin-spellcheck": "^0.0.17",
|
50
52
|
"identity-obj-proxy": "^3.0.0",
|
51
53
|
"jed": "^1.1.1",
|
52
54
|
"jest-cli": "^23.6.0",
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class UploadReportJobTest < ActiveJob::TestCase
|
4
|
+
include FolderIsolation
|
5
|
+
|
6
|
+
test 'returns aborted state when disconnected' do
|
7
|
+
organization = FactoryBot.create(:organization)
|
8
|
+
Organization.any_instance.stubs(:owner_details).returns(
|
9
|
+
'upstreamConsumer' => {
|
10
|
+
'idCert' => 'TEST_CERT',
|
11
|
+
}
|
12
|
+
)
|
13
|
+
FactoryBot.create(:setting, :name => 'content_disconnected', :value => true)
|
14
|
+
|
15
|
+
ForemanInventoryUpload::Async::UploadReportJob.perform_now('', organization.id)
|
16
|
+
|
17
|
+
label = ForemanInventoryUpload::Async::UploadReportJob.output_label(organization.id)
|
18
|
+
progress_output = ForemanInventoryUpload::Async::ProgressOutput.get(label)
|
19
|
+
assert_match(/Upload was stopped/, progress_output.full_output)
|
20
|
+
assert_match(/exit 1/, progress_output.status)
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'returns aborted state when no certificate defined on organization' do
|
24
|
+
organization = FactoryBot.create(:organization)
|
25
|
+
Organization.any_instance.expects(:owner_details).returns(nil)
|
26
|
+
|
27
|
+
ForemanInventoryUpload::Async::UploadReportJob.perform_now('', organization.id)
|
28
|
+
|
29
|
+
label = ForemanInventoryUpload::Async::UploadReportJob.output_label(organization.id)
|
30
|
+
progress_output = ForemanInventoryUpload::Async::ProgressOutput.get(label)
|
31
|
+
assert_match(/Skipping organization/, progress_output.full_output)
|
32
|
+
assert_match(/exit 1/, progress_output.status)
|
33
|
+
end
|
34
|
+
end
|
@@ -13,6 +13,8 @@ class MetadataGeneratorTest < ActiveSupport::TestCase
|
|
13
13
|
|
14
14
|
assert_not_nil actual['report_id']
|
15
15
|
assert_equal 'Satellite', actual['source']
|
16
|
+
assert_not_nil (actual_metadata = actual['source_metadata'])
|
17
|
+
assert_equal ForemanRhCloud::VERSION, actual_metadata['foreman_rh_cloud_version']
|
16
18
|
assert_equal({}, actual['report_slices'])
|
17
19
|
end
|
18
20
|
|
@@ -9,6 +9,7 @@ class ReportGeneratorTest < ActiveSupport::TestCase
|
|
9
9
|
|
10
10
|
@host = FactoryBot.create(
|
11
11
|
:host,
|
12
|
+
:redhat,
|
12
13
|
:with_subscription,
|
13
14
|
:with_content,
|
14
15
|
content_view: cv.first,
|
@@ -264,6 +265,22 @@ class ReportGeneratorTest < ActiveSupport::TestCase
|
|
264
265
|
assert_equal 1, generator.hosts_count
|
265
266
|
end
|
266
267
|
|
268
|
+
test 'include also hosts with non-redhat OS' do
|
269
|
+
os = @host.operatingsystem
|
270
|
+
os.name = 'Centos'
|
271
|
+
os.save!
|
272
|
+
|
273
|
+
# make a_host last
|
274
|
+
batch = ForemanInventoryUpload::Generators::Queries.for_org(@host.organization_id).first
|
275
|
+
generator = create_generator(batch)
|
276
|
+
|
277
|
+
json_str = generator.render
|
278
|
+
actual = JSON.parse(json_str.join("\n"))
|
279
|
+
|
280
|
+
assert_equal 'slice_123', actual['report_slice_id']
|
281
|
+
assert_equal 1, generator.hosts_count
|
282
|
+
end
|
283
|
+
|
267
284
|
test 'shows system_memory_bytes in bytes' do
|
268
285
|
FactoryBot.create(:fact_value, fact_name: fact_names['memory::memtotal'], value: '1', host: @host)
|
269
286
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import ForemanInventoryUpload from './ForemanInventoryUpload';
|
2
2
|
import InsightsCloudSync from './InsightsCloudSync';
|
3
|
+
import InsightsHostDetailsTab from './InsightsHostDetailsTab';
|
3
4
|
|
4
5
|
export default [
|
5
6
|
{ name: 'ForemanInventoryUpload', type: ForemanInventoryUpload },
|
6
7
|
{ name: 'InsightsCloudSync', type: InsightsCloudSync },
|
8
|
+
{ name: 'InsightsHostDetailsTab', type: InsightsHostDetailsTab },
|
7
9
|
];
|
@@ -1,10 +1,12 @@
|
|
1
1
|
import { combineReducers } from 'redux';
|
2
2
|
import inventoryUploadReducers from './ForemanInventoryUpload/ForemanInventoryUploadReducers';
|
3
3
|
import insightsReducers from './InsightsCloudSync/InsightsCloudSyncReducers';
|
4
|
+
import { hostInsightsReducers } from './InsightsHostDetailsTab';
|
4
5
|
|
5
6
|
export default {
|
6
7
|
ForemanRhCloud: combineReducers({
|
7
8
|
...inventoryUploadReducers,
|
8
9
|
...insightsReducers,
|
10
|
+
...hostInsightsReducers,
|
9
11
|
}),
|
10
12
|
};
|
@@ -1,5 +1,10 @@
|
|
1
1
|
export const selectForemanRhCloud = state => state.ForemanRhCloud;
|
2
|
+
|
2
3
|
export const selectForemanInventoryUpload = state =>
|
3
4
|
selectForemanRhCloud(state).inventoryUpload;
|
5
|
+
|
4
6
|
export const selectInsightsCloudSync = state =>
|
5
7
|
selectForemanRhCloud(state).InsightsCloudSync;
|
8
|
+
|
9
|
+
export const selectHostInsights = state =>
|
10
|
+
selectForemanRhCloud(state).hostInsights;
|
@@ -1,10 +1,12 @@
|
|
1
1
|
export const rhCloudStateWrapper = (
|
2
2
|
inventoryState = {},
|
3
|
-
insightsState = {}
|
3
|
+
insightsState = {},
|
4
|
+
hostInsightsState = {}
|
4
5
|
) => ({
|
5
6
|
ForemanRhCloud: {
|
6
7
|
inventoryUpload: { ...inventoryState },
|
7
8
|
InsightsCloudSync: { ...insightsState },
|
9
|
+
hostInsights: { ...hostInsightsState },
|
8
10
|
},
|
9
11
|
});
|
10
12
|
|
@@ -13,3 +15,6 @@ export const inventoryStateWrapper = innerState =>
|
|
13
15
|
|
14
16
|
export const insightsStateWrapper = innerState =>
|
15
17
|
rhCloudStateWrapper({}, innerState);
|
18
|
+
|
19
|
+
export const hostInsightsStateWrapper = innerState =>
|
20
|
+
rhCloudStateWrapper({}, {}, innerState);
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { orderBy } from 'lodash';
|
4
|
+
import { Grid, ListView, noop } from 'patternfly-react';
|
5
|
+
import ListItem from './components/ListItem';
|
6
|
+
import './InsightsTab.scss';
|
7
|
+
|
8
|
+
class InsightsHostDetailsTab extends React.Component {
|
9
|
+
componentDidMount() {
|
10
|
+
const { fetchHits, hostID } = this.props;
|
11
|
+
fetchHits(hostID);
|
12
|
+
}
|
13
|
+
|
14
|
+
render() {
|
15
|
+
const { hits } = this.props;
|
16
|
+
|
17
|
+
if (!hits.length) {
|
18
|
+
return <h2>No recommendations were found for this host!</h2>;
|
19
|
+
}
|
20
|
+
const hitsSorted = orderBy(hits, ['insights_hit.total_risk'], ['desc']);
|
21
|
+
const items = hitsSorted.map(
|
22
|
+
(
|
23
|
+
{
|
24
|
+
insights_hit: {
|
25
|
+
title,
|
26
|
+
total_risk: totalRisk,
|
27
|
+
results_url: resultsUrl,
|
28
|
+
solution_url: solutionUrl,
|
29
|
+
},
|
30
|
+
},
|
31
|
+
index
|
32
|
+
) => (
|
33
|
+
<ListItem
|
34
|
+
key={index}
|
35
|
+
title={title}
|
36
|
+
totalRisk={totalRisk}
|
37
|
+
resultsUrl={resultsUrl}
|
38
|
+
solutionUrl={solutionUrl}
|
39
|
+
/>
|
40
|
+
)
|
41
|
+
);
|
42
|
+
return (
|
43
|
+
<Grid.Row>
|
44
|
+
<Grid.Col xs={12}>
|
45
|
+
<h2>Recommendations</h2>
|
46
|
+
<ListView id="hits_list">{items}</ListView>
|
47
|
+
</Grid.Col>
|
48
|
+
</Grid.Row>
|
49
|
+
);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
InsightsHostDetailsTab.propTypes = {
|
54
|
+
hostID: PropTypes.number.isRequired,
|
55
|
+
fetchHits: PropTypes.func,
|
56
|
+
hits: PropTypes.array,
|
57
|
+
};
|
58
|
+
|
59
|
+
InsightsHostDetailsTab.defaultProps = {
|
60
|
+
fetchHits: noop,
|
61
|
+
hits: [],
|
62
|
+
};
|
63
|
+
|
64
|
+
export default InsightsHostDetailsTab;
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#host_details_insights_react_container {
|
2
|
+
#btn_toolbar {
|
3
|
+
float: right;
|
4
|
+
}
|
5
|
+
|
6
|
+
#btn_fullscreen {
|
7
|
+
margin-left: 5px;
|
8
|
+
|
9
|
+
.fa-arrows-alt {
|
10
|
+
margin-left: 5px;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
h2 {
|
15
|
+
margin-top: 5px;
|
16
|
+
}
|
17
|
+
|
18
|
+
#hits_list {
|
19
|
+
max-height: 650px;
|
20
|
+
overflow-y: scroll;
|
21
|
+
overflow-x: hidden;
|
22
|
+
margin-top: 15px;
|
23
|
+
|
24
|
+
.list-view-pf-expand {
|
25
|
+
padding: 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
.list-group-item-header {
|
29
|
+
.list-view-pf-expand .fa-angle-right {
|
30
|
+
margin-top: 6px;
|
31
|
+
}
|
32
|
+
|
33
|
+
.list-view-pf-main-info .list-view-pf-description {
|
34
|
+
width: 83%;
|
35
|
+
|
36
|
+
.list-group-item-heading {
|
37
|
+
width: 375px;
|
38
|
+
}
|
39
|
+
|
40
|
+
p {
|
41
|
+
margin: 0;
|
42
|
+
font-size: 14px;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
.list-view-pf-additional-info {
|
47
|
+
.risk-label {
|
48
|
+
padding: 5px 8px;
|
49
|
+
border-radius: 12px;
|
50
|
+
|
51
|
+
&.Low {
|
52
|
+
background-color: #e7f1fa;
|
53
|
+
}
|
54
|
+
|
55
|
+
&.Moderate {
|
56
|
+
background-color: #fdf7e7;
|
57
|
+
}
|
58
|
+
|
59
|
+
&.Important {
|
60
|
+
background-color: #f9dddd;
|
61
|
+
}
|
62
|
+
|
63
|
+
&.Critical {
|
64
|
+
background-color: #ffecec;
|
65
|
+
}
|
66
|
+
|
67
|
+
p {
|
68
|
+
margin: 0;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
&::-webkit-scrollbar {
|
75
|
+
width: 12px;
|
76
|
+
height: 12px;
|
77
|
+
}
|
78
|
+
|
79
|
+
&::-webkit-scrollbar-thumb {
|
80
|
+
background: #0e0e0e6e;
|
81
|
+
border-radius: 6px;
|
82
|
+
border: 3px solid transparent;
|
83
|
+
background-clip: content-box;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import API from 'foremanReact/API';
|
2
|
+
import { insightsCloudUrl } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
|
3
|
+
import {
|
4
|
+
INSIGHTS_HITS_REQUEST,
|
5
|
+
INSIGHTS_HITS_SUCCESS,
|
6
|
+
INSIGHTS_HITS_FAILURE,
|
7
|
+
} from './InsightsTabConstants';
|
8
|
+
|
9
|
+
export const fetchHits = hostID => async dispatch => {
|
10
|
+
try {
|
11
|
+
dispatch({
|
12
|
+
type: INSIGHTS_HITS_REQUEST,
|
13
|
+
payload: {},
|
14
|
+
});
|
15
|
+
const {
|
16
|
+
data: { hits },
|
17
|
+
} = await API.get(insightsCloudUrl(`hits/${hostID}`));
|
18
|
+
dispatch({
|
19
|
+
type: INSIGHTS_HITS_SUCCESS,
|
20
|
+
payload: { hits },
|
21
|
+
});
|
22
|
+
} catch (error) {
|
23
|
+
dispatch({
|
24
|
+
type: INSIGHTS_HITS_FAILURE,
|
25
|
+
payload: {
|
26
|
+
error: error.message,
|
27
|
+
},
|
28
|
+
});
|
29
|
+
}
|
30
|
+
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import Immutable from 'seamless-immutable';
|
2
|
+
import {
|
3
|
+
INSIGHTS_HITS_SUCCESS,
|
4
|
+
INSIGHTS_HITS_FAILURE,
|
5
|
+
} from './InsightsTabConstants';
|
6
|
+
|
7
|
+
const initialState = Immutable({
|
8
|
+
hits: [],
|
9
|
+
});
|
10
|
+
|
11
|
+
export default (state = initialState, action) => {
|
12
|
+
const { payload: { hits, error } = {} } = action;
|
13
|
+
|
14
|
+
switch (action.type) {
|
15
|
+
case INSIGHTS_HITS_SUCCESS:
|
16
|
+
return state.merge({
|
17
|
+
hits,
|
18
|
+
});
|
19
|
+
case INSIGHTS_HITS_FAILURE:
|
20
|
+
return state.merge({
|
21
|
+
error,
|
22
|
+
});
|
23
|
+
default:
|
24
|
+
return state;
|
25
|
+
}
|
26
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
export const hostID = 1234;
|
2
|
+
|
3
|
+
export const hits = [
|
4
|
+
{
|
5
|
+
insights_hit: {
|
6
|
+
hostname: 'my-host.example.com',
|
7
|
+
rhel_version: '7.8',
|
8
|
+
uuid: '4739b323-a343-4e89-b71b-81991b8dc656',
|
9
|
+
last_seen: '2020-08-19T04:43:09.068706Z',
|
10
|
+
title:
|
11
|
+
'New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled',
|
12
|
+
solution_url: 'https://access.redhat.com/node/3359651',
|
13
|
+
total_risk: 2,
|
14
|
+
likelihood: 2,
|
15
|
+
publish_date: '2018-04-16T10:03:16Z',
|
16
|
+
results_url:
|
17
|
+
'https://cloud.redhat.com/insights/advisor/recommendations/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/4739b323-a343-4e89-b71b-81991b8dc656/',
|
18
|
+
},
|
19
|
+
},
|
20
|
+
];
|
21
|
+
|
22
|
+
export const props = {
|
23
|
+
hostID,
|
24
|
+
hits,
|
25
|
+
};
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import InsightsTab from '../InsightsTab';
|
4
|
+
import { props } from './InsightsTab.fixtures';
|
5
|
+
|
6
|
+
const fixtures = {
|
7
|
+
'render with props': props,
|
8
|
+
};
|
9
|
+
|
10
|
+
describe('InsightsTab', () => {
|
11
|
+
describe('rendering', () =>
|
12
|
+
testComponentSnapshotsWithFixtures(InsightsTab, fixtures));
|
13
|
+
});
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { testActionSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
import API from 'foremanReact/API';
|
3
|
+
import { fetchHits } from '../InsightsTabActions';
|
4
|
+
import { hostID, hits } from './InsightsTab.fixtures';
|
5
|
+
|
6
|
+
jest.mock('foremanReact/API');
|
7
|
+
API.get.mockImplementation(async () => hits);
|
8
|
+
|
9
|
+
const fixtures = {
|
10
|
+
'should fetchHits': () => fetchHits(hostID),
|
11
|
+
};
|
12
|
+
|
13
|
+
describe('InsightsTab actions', () => testActionSnapshotWithFixtures(fixtures));
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { IntegrationTestHelper } from 'react-redux-test-utils';
|
3
|
+
|
4
|
+
import InsightsTab from '../index';
|
5
|
+
import reducers from '../../ForemanRhCloudReducers';
|
6
|
+
import { hostID } from './InsightsTab.fixtures';
|
7
|
+
|
8
|
+
describe('InsightsTab integration test', () => {
|
9
|
+
it('should flow', async () => {
|
10
|
+
const integrationTestHelper = new IntegrationTestHelper(reducers);
|
11
|
+
const component = integrationTestHelper.mount(
|
12
|
+
<InsightsTab hostID={hostID} />
|
13
|
+
);
|
14
|
+
component.update();
|
15
|
+
/** Create a Flow test */
|
16
|
+
});
|
17
|
+
});
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { testReducerSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
import reducer from '../InsightsTabReducer';
|
3
|
+
import { hits } from './InsightsTab.fixtures';
|
4
|
+
import {
|
5
|
+
INSIGHTS_HITS_REQUEST,
|
6
|
+
INSIGHTS_HITS_SUCCESS,
|
7
|
+
INSIGHTS_HITS_FAILURE,
|
8
|
+
} from '../InsightsTabConstants';
|
9
|
+
|
10
|
+
const fixtures = {
|
11
|
+
'should return the initial state': {},
|
12
|
+
'should handle INSIGHTS_HITS_REQUEST': {
|
13
|
+
action: {
|
14
|
+
type: INSIGHTS_HITS_REQUEST,
|
15
|
+
payload: {},
|
16
|
+
},
|
17
|
+
},
|
18
|
+
'should handle INSIGHTS_HITS_SUCCESS': {
|
19
|
+
action: {
|
20
|
+
type: INSIGHTS_HITS_SUCCESS,
|
21
|
+
payload: { hits },
|
22
|
+
},
|
23
|
+
},
|
24
|
+
'should handle INSIGHTS_HITS_FAILURE': {
|
25
|
+
action: {
|
26
|
+
type: INSIGHTS_HITS_FAILURE,
|
27
|
+
payload: {
|
28
|
+
error: 'some-error',
|
29
|
+
},
|
30
|
+
},
|
31
|
+
},
|
32
|
+
};
|
33
|
+
|
34
|
+
describe('AccountList reducer', () =>
|
35
|
+
testReducerSnapshotWithFixtures(reducer, fixtures));
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { testSelectorsSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
import { hostInsightsStateWrapper } from '../../ForemanRhCloudTestHelpers';
|
3
|
+
import { hits } from './InsightsTab.fixtures';
|
4
|
+
import { selectHits } from '../InsightsTabSelectors';
|
5
|
+
|
6
|
+
const state = hostInsightsStateWrapper({ hits });
|
7
|
+
|
8
|
+
const fixtures = {
|
9
|
+
'should return hits': () => selectHits(state),
|
10
|
+
};
|
11
|
+
|
12
|
+
describe('InsightsTab selectors', () =>
|
13
|
+
testSelectorsSnapshotWithFixtures(fixtures));
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`InsightsTab rendering render with props 1`] = `
|
4
|
+
<Row
|
5
|
+
bsClass="row"
|
6
|
+
componentClass="div"
|
7
|
+
>
|
8
|
+
<Col
|
9
|
+
bsClass="col"
|
10
|
+
componentClass="div"
|
11
|
+
xs={12}
|
12
|
+
>
|
13
|
+
<h2>
|
14
|
+
Recommendations
|
15
|
+
</h2>
|
16
|
+
<ListView
|
17
|
+
className=""
|
18
|
+
id="hits_list"
|
19
|
+
>
|
20
|
+
<ListItem
|
21
|
+
key="0"
|
22
|
+
resultsUrl="https://cloud.redhat.com/insights/advisor/recommendations/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/4739b323-a343-4e89-b71b-81991b8dc656/"
|
23
|
+
solutionUrl="https://access.redhat.com/node/3359651"
|
24
|
+
title="New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled"
|
25
|
+
totalRisk={2}
|
26
|
+
/>
|
27
|
+
</ListView>
|
28
|
+
</Col>
|
29
|
+
</Row>
|
30
|
+
`;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`InsightsTab actions should fetchHits 1`] = `
|
4
|
+
Array [
|
5
|
+
Array [
|
6
|
+
Object {
|
7
|
+
"payload": Object {},
|
8
|
+
"type": "INSIGHTS_HITS_REQUEST",
|
9
|
+
},
|
10
|
+
],
|
11
|
+
Array [
|
12
|
+
Object {
|
13
|
+
"payload": Object {
|
14
|
+
"error": "Cannot read property 'hits' of undefined",
|
15
|
+
},
|
16
|
+
"type": "INSIGHTS_HITS_FAILURE",
|
17
|
+
},
|
18
|
+
],
|
19
|
+
]
|
20
|
+
`;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`AccountList reducer should handle INSIGHTS_HITS_FAILURE 1`] = `
|
4
|
+
Object {
|
5
|
+
"error": "some-error",
|
6
|
+
"hits": Array [],
|
7
|
+
}
|
8
|
+
`;
|
9
|
+
|
10
|
+
exports[`AccountList reducer should handle INSIGHTS_HITS_REQUEST 1`] = `
|
11
|
+
Object {
|
12
|
+
"hits": Array [],
|
13
|
+
}
|
14
|
+
`;
|
15
|
+
|
16
|
+
exports[`AccountList reducer should handle INSIGHTS_HITS_SUCCESS 1`] = `
|
17
|
+
Object {
|
18
|
+
"hits": Array [
|
19
|
+
Object {
|
20
|
+
"insights_hit": Object {
|
21
|
+
"hostname": "my-host.example.com",
|
22
|
+
"last_seen": "2020-08-19T04:43:09.068706Z",
|
23
|
+
"likelihood": 2,
|
24
|
+
"publish_date": "2018-04-16T10:03:16Z",
|
25
|
+
"results_url": "https://cloud.redhat.com/insights/advisor/recommendations/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/4739b323-a343-4e89-b71b-81991b8dc656/",
|
26
|
+
"rhel_version": "7.8",
|
27
|
+
"solution_url": "https://access.redhat.com/node/3359651",
|
28
|
+
"title": "New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled",
|
29
|
+
"total_risk": 2,
|
30
|
+
"uuid": "4739b323-a343-4e89-b71b-81991b8dc656",
|
31
|
+
},
|
32
|
+
},
|
33
|
+
],
|
34
|
+
}
|
35
|
+
`;
|
36
|
+
|
37
|
+
exports[`AccountList reducer should return the initial state 1`] = `
|
38
|
+
Object {
|
39
|
+
"hits": Array [],
|
40
|
+
}
|
41
|
+
`;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`InsightsTab selectors should return hits 1`] = `
|
4
|
+
Array [
|
5
|
+
Object {
|
6
|
+
"insights_hit": Object {
|
7
|
+
"hostname": "my-host.example.com",
|
8
|
+
"last_seen": "2020-08-19T04:43:09.068706Z",
|
9
|
+
"likelihood": 2,
|
10
|
+
"publish_date": "2018-04-16T10:03:16Z",
|
11
|
+
"results_url": "https://cloud.redhat.com/insights/advisor/recommendations/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/4739b323-a343-4e89-b71b-81991b8dc656/",
|
12
|
+
"rhel_version": "7.8",
|
13
|
+
"solution_url": "https://access.redhat.com/node/3359651",
|
14
|
+
"title": "New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled",
|
15
|
+
"total_risk": 2,
|
16
|
+
"uuid": "4739b323-a343-4e89-b71b-81991b8dc656",
|
17
|
+
},
|
18
|
+
},
|
19
|
+
]
|
20
|
+
`;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import React, { Fragment } from 'react';
|
2
|
+
import { ListView, Icon } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
const labelMapper = {
|
6
|
+
1: 'Low',
|
7
|
+
2: 'Moderate',
|
8
|
+
3: 'Important',
|
9
|
+
4: 'Critical',
|
10
|
+
};
|
11
|
+
|
12
|
+
const ListItem = ({ title, totalRisk, resultsUrl, solutionUrl }) => {
|
13
|
+
const heading = (
|
14
|
+
<p className="ellipsis list-item-heading" title={title}>
|
15
|
+
{title}
|
16
|
+
</p>
|
17
|
+
);
|
18
|
+
|
19
|
+
const riskLabel = labelMapper[totalRisk];
|
20
|
+
const additionalInfo = [
|
21
|
+
<span key={`risk-info-${title}`} className={`risk-label ${riskLabel}`}>
|
22
|
+
<p>{riskLabel}</p>
|
23
|
+
</span>,
|
24
|
+
];
|
25
|
+
|
26
|
+
const knowledgebaseLink = solutionUrl && (
|
27
|
+
<p>
|
28
|
+
<a href={solutionUrl} target="_blank" rel="noopener noreferrer">
|
29
|
+
Knowledgebase article <Icon name="external-link" />
|
30
|
+
</a>
|
31
|
+
</p>
|
32
|
+
);
|
33
|
+
|
34
|
+
const insightsCloudLink = resultsUrl && (
|
35
|
+
<p>
|
36
|
+
<a href={resultsUrl} target="_blank" rel="noopener noreferrer">
|
37
|
+
Read more about it in RH cloud insights <Icon name="external-link" />
|
38
|
+
</a>
|
39
|
+
</p>
|
40
|
+
);
|
41
|
+
|
42
|
+
return (
|
43
|
+
<ListView.Item
|
44
|
+
heading={heading}
|
45
|
+
additionalInfo={additionalInfo}
|
46
|
+
hideCloseIcon
|
47
|
+
>
|
48
|
+
<Fragment>
|
49
|
+
<p>{title}</p>
|
50
|
+
{knowledgebaseLink}
|
51
|
+
{insightsCloudLink}
|
52
|
+
</Fragment>
|
53
|
+
</ListView.Item>
|
54
|
+
);
|
55
|
+
};
|
56
|
+
|
57
|
+
ListItem.propTypes = {
|
58
|
+
title: PropTypes.string.isRequired,
|
59
|
+
totalRisk: PropTypes.number.isRequired,
|
60
|
+
resultsUrl: PropTypes.string,
|
61
|
+
solutionUrl: PropTypes.string,
|
62
|
+
};
|
63
|
+
|
64
|
+
ListItem.defaultProps = {
|
65
|
+
resultsUrl: '',
|
66
|
+
solutionUrl: '',
|
67
|
+
};
|
68
|
+
|
69
|
+
export default ListItem;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default } from './ListItem';
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { bindActionCreators } from 'redux';
|
2
|
+
import { connect } from 'react-redux';
|
3
|
+
import InsightsTab from './InsightsTab';
|
4
|
+
import * as actions from './InsightsTabActions';
|
5
|
+
import reducer from './InsightsTabReducer';
|
6
|
+
import { selectHits } from './InsightsTabSelectors';
|
7
|
+
|
8
|
+
// map state to props
|
9
|
+
const mapStateToProps = state => ({
|
10
|
+
hits: selectHits(state),
|
11
|
+
});
|
12
|
+
|
13
|
+
// map action dispatchers to props
|
14
|
+
const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
|
15
|
+
|
16
|
+
// export reducers
|
17
|
+
export const hostInsightsReducers = { hostInsights: reducer };
|
18
|
+
|
19
|
+
// export connected component
|
20
|
+
export default connect(mapStateToProps, mapDispatchToProps)(InsightsTab);
|
@@ -6,6 +6,7 @@ Object {
|
|
6
6
|
"InsightsCloudSync": Object {
|
7
7
|
"insightsChild": Object {},
|
8
8
|
},
|
9
|
+
"hostInsights": Object {},
|
9
10
|
"inventoryUpload": Object {},
|
10
11
|
},
|
11
12
|
}
|
@@ -15,6 +16,7 @@ exports[`ForemanRhCloud helpers should return inventory wrapper 1`] = `
|
|
15
16
|
Object {
|
16
17
|
"ForemanRhCloud": Object {
|
17
18
|
"InsightsCloudSync": Object {},
|
19
|
+
"hostInsights": Object {},
|
18
20
|
"inventoryUpload": Object {
|
19
21
|
"inventoryChild": Object {},
|
20
22
|
},
|
@@ -28,6 +30,7 @@ Object {
|
|
28
30
|
"InsightsCloudSync": Object {
|
29
31
|
"insightsChild": Object {},
|
30
32
|
},
|
33
|
+
"hostInsights": Object {},
|
31
34
|
"inventoryUpload": Object {
|
32
35
|
"inventoryChild": Object {},
|
33
36
|
},
|
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: 1.0.
|
4
|
+
version: 1.0.11
|
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: 2020-
|
11
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: katello
|
@@ -109,10 +109,12 @@ files:
|
|
109
109
|
- app/controllers/foreman_inventory_upload/tasks_controller.rb
|
110
110
|
- app/controllers/foreman_inventory_upload/uploads_controller.rb
|
111
111
|
- app/controllers/foreman_rh_cloud/react_controller.rb
|
112
|
+
- app/controllers/insights_cloud/hits_controller.rb
|
112
113
|
- app/controllers/insights_cloud/settings_controller.rb
|
113
114
|
- app/controllers/insights_cloud/tasks_controller.rb
|
114
115
|
- app/helpers/foreman_inventory_upload_helper.rb
|
115
116
|
- app/helpers/foreman_inventory_upload_host_helper.rb
|
117
|
+
- app/models/concerns/rh_cloud_host.rb
|
116
118
|
- app/models/insights_facet.rb
|
117
119
|
- app/models/insights_hit.rb
|
118
120
|
- app/models/inventory_sync/inventory_status.rb
|
@@ -120,6 +122,7 @@ files:
|
|
120
122
|
- app/overrides/hosts_list.rb
|
121
123
|
- app/views/foreman_rh_cloud/react/insights_cloud.html.erb
|
122
124
|
- app/views/foreman_rh_cloud/react/inventory_upload.html.erb
|
125
|
+
- app/views/hosts/_insights_tab.html.erb
|
123
126
|
- app/views/layouts/foreman_rh_cloud/application.html.erb
|
124
127
|
- config/routes.rb
|
125
128
|
- db/migrate/20191215104806_create_insights_hits.foreman_inventory_upload.rb
|
@@ -150,7 +153,8 @@ files:
|
|
150
153
|
- lib/inventory_sync/async/host_result.rb
|
151
154
|
- lib/inventory_sync/async/inventory_full_sync.rb
|
152
155
|
- lib/tasks/foreman_rh_cloud_tasks.rake
|
153
|
-
- lib/tasks/
|
156
|
+
- lib/tasks/insights.rake
|
157
|
+
- lib/tasks/rh_cloud_inventory.rake
|
154
158
|
- locale/Makefile
|
155
159
|
- locale/en/foreman_rh_cloud.po
|
156
160
|
- locale/foreman_rh_cloud.pot
|
@@ -164,6 +168,7 @@ files:
|
|
164
168
|
- test/factories/inventory_upload_factories.rb
|
165
169
|
- test/jobs/insights_full_sync_test.rb
|
166
170
|
- test/jobs/inventory_full_sync_test.rb
|
171
|
+
- test/jobs/upload_report_job_test.rb
|
167
172
|
- test/test_plugin_helper.rb
|
168
173
|
- test/unit/archived_report_generator_test.rb
|
169
174
|
- test/unit/fact_helpers_test.rb
|
@@ -458,6 +463,25 @@ files:
|
|
458
463
|
- webpack/InsightsCloudSync/__tests__/InsightsCloudSyncHelpers.test.js
|
459
464
|
- webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncHelpers.test.js.snap
|
460
465
|
- webpack/InsightsCloudSync/index.js
|
466
|
+
- webpack/InsightsHostDetailsTab/InsightsTab.js
|
467
|
+
- webpack/InsightsHostDetailsTab/InsightsTab.scss
|
468
|
+
- webpack/InsightsHostDetailsTab/InsightsTabActions.js
|
469
|
+
- webpack/InsightsHostDetailsTab/InsightsTabConstants.js
|
470
|
+
- webpack/InsightsHostDetailsTab/InsightsTabReducer.js
|
471
|
+
- webpack/InsightsHostDetailsTab/InsightsTabSelectors.js
|
472
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTab.fixtures.js
|
473
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js
|
474
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabActions.test.js
|
475
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabIntegration.test.js
|
476
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabReducer.test.js
|
477
|
+
- webpack/InsightsHostDetailsTab/__tests__/InsightsTabSelectors.test.js
|
478
|
+
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTab.test.js.snap
|
479
|
+
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabActions.test.js.snap
|
480
|
+
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabReducer.test.js.snap
|
481
|
+
- webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabSelectors.test.js.snap
|
482
|
+
- webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js
|
483
|
+
- webpack/InsightsHostDetailsTab/components/ListItem/index.js
|
484
|
+
- webpack/InsightsHostDetailsTab/index.js
|
461
485
|
- webpack/__mocks__/foremanReact/API.js
|
462
486
|
- webpack/__mocks__/foremanReact/common/I18n.js
|
463
487
|
- webpack/__mocks__/foremanReact/common/helpers.js
|
@@ -498,23 +522,24 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
498
522
|
- !ruby/object:Gem::Version
|
499
523
|
version: '0'
|
500
524
|
requirements: []
|
501
|
-
rubygems_version: 3.0.
|
525
|
+
rubygems_version: 3.0.8
|
502
526
|
signing_key:
|
503
527
|
specification_version: 4
|
504
528
|
summary: Summary of ForemanRhCloud.
|
505
529
|
test_files:
|
506
|
-
- test/controllers/uploads_controller_test.rb
|
507
|
-
- test/controllers/insights_sync/settings_controller_test.rb
|
508
|
-
- test/controllers/accounts_controller_test.rb
|
509
|
-
- test/controllers/reports_controller_test.rb
|
510
530
|
- test/test_plugin_helper.rb
|
511
|
-
- test/jobs/insights_full_sync_test.rb
|
512
|
-
- test/jobs/inventory_full_sync_test.rb
|
513
531
|
- test/factories/inventory_upload_factories.rb
|
514
532
|
- test/factories/insights_factories.rb
|
515
|
-
- test/
|
533
|
+
- test/controllers/reports_controller_test.rb
|
534
|
+
- test/controllers/uploads_controller_test.rb
|
535
|
+
- test/controllers/accounts_controller_test.rb
|
536
|
+
- test/controllers/insights_sync/settings_controller_test.rb
|
537
|
+
- test/unit/slice_generator_test.rb
|
516
538
|
- test/unit/metadata_generator_test.rb
|
539
|
+
- test/unit/shell_process_job_test.rb
|
517
540
|
- test/unit/insights_facet_test.rb
|
518
|
-
- test/unit/fact_helpers_test.rb
|
519
541
|
- test/unit/archived_report_generator_test.rb
|
520
|
-
- test/unit/
|
542
|
+
- test/unit/fact_helpers_test.rb
|
543
|
+
- test/jobs/inventory_full_sync_test.rb
|
544
|
+
- test/jobs/insights_full_sync_test.rb
|
545
|
+
- test/jobs/upload_report_job_test.rb
|