foreman_rh_cloud 13.0.8 → 13.0.10
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/app/controllers/concerns/inventory_upload/report_actions.rb +8 -1
- data/app/controllers/foreman_inventory_upload/accounts_controller.rb +82 -7
- data/app/controllers/foreman_inventory_upload/api/tasks_controller.rb +110 -0
- data/app/controllers/foreman_inventory_upload/reports_controller.rb +41 -17
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +0 -9
- data/config/routes.rb +4 -2
- data/db/migrate/20251209163012_drop_task_output_tables.foreman_rh_cloud.rb +24 -0
- data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +1 -1
- data/lib/foreman_inventory_upload/async/host_inventory_report_job.rb +39 -0
- data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +1 -23
- data/lib/foreman_inventory_upload/async/upload_report_direct_job.rb +171 -0
- data/lib/foreman_inventory_upload.rb +0 -4
- data/lib/foreman_rh_cloud/plugin.rb +1 -0
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +0 -2
- data/lib/tasks/rh_cloud_inventory.rake +4 -2
- data/package.json +1 -1
- data/test/controllers/accounts_controller_test.rb +10 -11
- data/test/controllers/insights_cloud/api/cloud_request_controller_test.rb +1 -2
- data/test/jobs/host_inventory_report_job_test.rb +161 -97
- data/test/jobs/queue_for_upload_job_test.rb +1 -12
- data/test/jobs/single_host_report_job_test.rb +36 -54
- data/test/jobs/upload_report_direct_job_test.rb +399 -0
- data/test/unit/rh_cloud_permissions_test.rb +2 -0
- data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +6 -6
- data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js +49 -34
- data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js +4 -5
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +15 -7
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +11 -11
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatus.fixtures.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatus.js +10 -14
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatusHelper.js +9 -4
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/__tests__/__snapshots__/ListItemStatus.test.js.snap +4 -4
- data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountList.test.js.snap +15 -9
- data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListActions.test.js.snap +7 -7
- data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +6 -6
- data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +12 -12
- data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +37 -130
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/Dashboard.test.js +60 -17
- data/webpack/ForemanInventoryUpload/Components/Dashboard/index.js +1 -34
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +0 -1
- data/webpack/ForemanInventoryUpload/Components/NavContainer/NavContainer.js +1 -26
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +24 -17
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +178 -8
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +2 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +69 -51
- data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +22 -9
- data/webpack/ForemanInventoryUpload/Components/TabHeader/__tests__/TabHeader.test.js +67 -4
- data/webpack/ForemanInventoryUpload/Components/TaskHistory/TaskHistory.js +140 -0
- data/webpack/ForemanInventoryUpload/Components/TaskHistory/index.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/TaskHistory/taskHistory.scss +40 -0
- data/webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js +340 -0
- data/webpack/ForemanInventoryUpload/Components/TaskProgress/index.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/TaskProgress/taskProgress.scss +8 -0
- data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +2 -2
- data/webpack/ForemanInventoryUpload/ForemanInventoryUploadReducers.js +0 -2
- data/webpack/ForemanInventoryUpload/__tests__/__snapshots__/ForemanInventoryHelpers.test.js.snap +1 -1
- data/webpack/ForemanRhCloudPages.js +0 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +11 -19
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationHelpers.js +1 -2
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +2 -4
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +77 -22
- data/webpack/__mocks__/foremanReact/components/common/dates/RelativeDateTime.js +14 -0
- data/webpack/__tests__/ForemanRhCloudHelpers.test.js +5 -1
- metadata +13 -68
- data/app/models/task_output_line.rb +0 -2
- data/app/models/task_output_status.rb +0 -2
- data/lib/foreman_inventory_upload/async/generate_report_job.rb +0 -61
- data/lib/foreman_inventory_upload/async/progress_output.rb +0 -38
- data/lib/foreman_inventory_upload/async/shell_process.rb +0 -77
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +0 -97
- data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +0 -55
- data/test/controllers/reports_controller_test.rb +0 -21
- data/test/controllers/uploads_controller_test.rb +0 -21
- data/test/jobs/generate_report_job_test.rb +0 -146
- data/test/jobs/upload_report_job_test.rb +0 -38
- data/test/unit/shell_process_job_test.rb +0 -29
- data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardActions.js +0 -88
- data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardConstants.js +0 -9
- data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardReducer.js +0 -68
- data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardSelectors.js +0 -17
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardActions.test.js +0 -51
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardIntegration.test.js +0 -17
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardReducer.test.js +0 -64
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardSelectors.test.js +0 -46
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/Dashboard.test.js.snap +0 -36
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardActions.test.js.snap +0 -76
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardReducer.test.js.snap +0 -44
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardSelectors.test.js.snap +0 -42
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.fixtures.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.js +0 -55
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModalHelper.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/FullScreenModal.test.js +0 -13
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/__snapshots__/FullScreenModal.test.js.snap +0 -65
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/fullScreenModal.scss +0 -20
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/index.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +0 -36
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.fixtures.js +0 -18
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.js +0 -65
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerateHelper.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/__tests__/ReportGenerate.test.js +0 -14
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/__tests__/__snapshots__/ReportGenerate.test.js.snap +0 -47
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/index.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/reportGenerate.scss +0 -0
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUpload.fixtures.js +0 -18
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUpload.js +0 -46
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUploadHelper.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/__tests__/ReportUpload.test.js +0 -14
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/__tests__/__snapshots__/ReportUpload.test.js.snap +0 -47
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/index.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/reportUpload.scss +0 -0
- data/webpack/ForemanInventoryUpload/Components/TabBody/TabBody.fixtures.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/TabBody/TabBody.js +0 -31
- data/webpack/ForemanInventoryUpload/Components/TabBody/TabBodyHelper.js +0 -0
- data/webpack/ForemanInventoryUpload/Components/TabBody/__tests__/TabBody.test.js +0 -13
- data/webpack/ForemanInventoryUpload/Components/TabBody/__tests__/__snapshots__/TabBody.test.js.snap +0 -19
- data/webpack/ForemanInventoryUpload/Components/TabBody/index.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/TabBody/tabBody.scss +0 -5
- data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.fixtures.js +0 -10
- data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.js +0 -110
- data/webpack/ForemanInventoryUpload/Components/Terminal/TerminalHelper.js +0 -6
- data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/Terminal.test.js +0 -34
- data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/__snapshots__/Terminal.test.js.snap +0 -98
- data/webpack/ForemanInventoryUpload/Components/Terminal/index.js +0 -1
- data/webpack/ForemanInventoryUpload/Components/Terminal/terminal.scss +0 -32
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +0 -112
- data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +0 -3
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
|
+
include Dynflow::Testing::Assertions
|
|
7
|
+
|
|
8
|
+
setup do
|
|
9
|
+
@organization = FactoryBot.create(:organization)
|
|
10
|
+
@uploads_folder = ForemanInventoryUpload.uploads_folder
|
|
11
|
+
@filename = File.join(@uploads_folder, 'test_report.tar.xz')
|
|
12
|
+
|
|
13
|
+
# Stub settings
|
|
14
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
15
|
+
Setting.stubs(:[]).with(:ssl_certificate).returns('/fake/cert.pem')
|
|
16
|
+
Setting.stubs(:[]).with(:ssl_priv_key).returns('/fake/key.pem')
|
|
17
|
+
|
|
18
|
+
# Stub ForemanRhCloud methods
|
|
19
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
20
|
+
|
|
21
|
+
# Stub organization owner details with certificate
|
|
22
|
+
@cert_data = {
|
|
23
|
+
'upstreamConsumer' => {
|
|
24
|
+
'idCert' => {
|
|
25
|
+
'cert' => 'FAKE CERTIFICATE',
|
|
26
|
+
'key' => 'FAKE KEY',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
Organization.any_instance.stubs(:owner_details).returns(@cert_data)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test 'plan sets input correctly' do
|
|
34
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
35
|
+
action.expects(:action_subject).with(@organization)
|
|
36
|
+
plan_action(action, @filename, @organization.id)
|
|
37
|
+
|
|
38
|
+
assert_equal @filename, action.input[:filename]
|
|
39
|
+
assert_equal @organization.id, action.input[:organization_id]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test 'output_label generates correct label' do
|
|
43
|
+
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
44
|
+
assert_equal "upload_for_#{@organization.id}", label
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test 'uses manifest certificate in regular mode' do
|
|
48
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
49
|
+
|
|
50
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
51
|
+
action.expects(:action_subject).with(@organization)
|
|
52
|
+
plan_action(action, @filename, @organization.id)
|
|
53
|
+
|
|
54
|
+
cert = action.send(:certificate)
|
|
55
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
56
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
test 'manifest_certificate extracts from organization owner_details' do
|
|
60
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
61
|
+
action.expects(:action_subject).with(@organization)
|
|
62
|
+
plan_action(action, @filename, @organization.id)
|
|
63
|
+
|
|
64
|
+
cert = action.send(:manifest_certificate)
|
|
65
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
66
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
test 'uses foreman certificate in IoP mode' do
|
|
70
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
71
|
+
File.stubs(:readable?).with('/fake/cert.pem').returns(true)
|
|
72
|
+
File.stubs(:readable?).with('/fake/key.pem').returns(true)
|
|
73
|
+
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
74
|
+
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
75
|
+
|
|
76
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
77
|
+
action.expects(:action_subject).with(@organization)
|
|
78
|
+
plan_action(action, @filename, @organization.id)
|
|
79
|
+
|
|
80
|
+
cert = action.send(:foreman_certificate)
|
|
81
|
+
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
82
|
+
assert_equal 'FOREMAN KEY', cert[:key]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
test 'certificate method returns manifest cert in regular mode' do
|
|
86
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
87
|
+
|
|
88
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
89
|
+
action.expects(:action_subject).with(@organization)
|
|
90
|
+
plan_action(action, @filename, @organization.id)
|
|
91
|
+
|
|
92
|
+
cert = action.send(:certificate)
|
|
93
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
94
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
test 'certificate method returns foreman cert in IoP mode' do
|
|
98
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
99
|
+
Setting.stubs(:[]).with(:ssl_certificate).returns('/fake/cert.pem')
|
|
100
|
+
Setting.stubs(:[]).with(:ssl_priv_key).returns('/fake/key.pem')
|
|
101
|
+
File.stubs(:readable?).with('/fake/cert.pem').returns(true)
|
|
102
|
+
File.stubs(:readable?).with('/fake/key.pem').returns(true)
|
|
103
|
+
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
104
|
+
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
105
|
+
|
|
106
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
107
|
+
action.expects(:action_subject).with(@organization)
|
|
108
|
+
plan_action(action, @filename, @organization.id)
|
|
109
|
+
|
|
110
|
+
cert = action.send(:certificate)
|
|
111
|
+
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
112
|
+
assert_equal 'FOREMAN KEY', cert[:key]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
test 'foreman_certificate raises error when certificate file is missing' do
|
|
116
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
117
|
+
Setting.stubs(:[]).with(:ssl_certificate).returns('/nonexistent/cert.pem')
|
|
118
|
+
Setting.stubs(:[]).with(:ssl_priv_key).returns('/fake/key.pem')
|
|
119
|
+
File.stubs(:readable?).with('/nonexistent/cert.pem').returns(false)
|
|
120
|
+
|
|
121
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
122
|
+
action.expects(:action_subject).with(@organization)
|
|
123
|
+
plan_action(action, @filename, @organization.id)
|
|
124
|
+
|
|
125
|
+
error = assert_raises(RuntimeError) do
|
|
126
|
+
action.send(:foreman_certificate)
|
|
127
|
+
end
|
|
128
|
+
assert_match(/SSL certificate file not found or not readable/, error.message)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
test 'foreman_certificate raises error when private key file is missing' do
|
|
132
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
133
|
+
Setting.stubs(:[]).with(:ssl_certificate).returns('/fake/cert.pem')
|
|
134
|
+
Setting.stubs(:[]).with(:ssl_priv_key).returns('/nonexistent/key.pem')
|
|
135
|
+
File.stubs(:readable?).with('/fake/cert.pem').returns(true)
|
|
136
|
+
File.stubs(:readable?).with('/nonexistent/key.pem').returns(false)
|
|
137
|
+
|
|
138
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
139
|
+
action.expects(:action_subject).with(@organization)
|
|
140
|
+
plan_action(action, @filename, @organization.id)
|
|
141
|
+
|
|
142
|
+
error = assert_raises(RuntimeError) do
|
|
143
|
+
action.send(:foreman_certificate)
|
|
144
|
+
end
|
|
145
|
+
assert_match(/SSL private key file not found or not readable/, error.message)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
test 'filename returns input filename' do
|
|
149
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
150
|
+
action.expects(:action_subject).with(@organization)
|
|
151
|
+
plan_action(action, @filename, @organization.id)
|
|
152
|
+
|
|
153
|
+
assert_equal @filename, action.send(:filename)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
test 'organization returns Organization from input organization_id' do
|
|
157
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
158
|
+
action.expects(:action_subject).with(@organization)
|
|
159
|
+
plan_action(action, @filename, @organization.id)
|
|
160
|
+
|
|
161
|
+
org = action.send(:organization)
|
|
162
|
+
assert_equal @organization.id, org.id
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
test 'content_disconnected? returns true when subscription_connection_enabled is false' do
|
|
166
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
167
|
+
|
|
168
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
169
|
+
action.expects(:action_subject).with(@organization)
|
|
170
|
+
plan_action(action, @filename, @organization.id)
|
|
171
|
+
|
|
172
|
+
assert action.send(:content_disconnected?)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
test 'content_disconnected? returns false when subscription_connection_enabled is true' do
|
|
176
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
177
|
+
|
|
178
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
179
|
+
action.expects(:action_subject).with(@organization)
|
|
180
|
+
plan_action(action, @filename, @organization.id)
|
|
181
|
+
|
|
182
|
+
refute action.send(:content_disconnected?)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
test 'content_disconnected? returns false when IoP mode is enabled even if subscription_connection_enabled is false' do
|
|
186
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
187
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
188
|
+
|
|
189
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
190
|
+
action.expects(:action_subject).with(@organization)
|
|
191
|
+
plan_action(action, @filename, @organization.id)
|
|
192
|
+
|
|
193
|
+
refute action.send(:content_disconnected?)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
test 'rescue_strategy_for_self returns Fail strategy' do
|
|
197
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
198
|
+
action.expects(:action_subject).with(@organization)
|
|
199
|
+
plan_action(action, @filename, @organization.id)
|
|
200
|
+
|
|
201
|
+
assert_equal Dynflow::Action::Rescue::Fail, action.send(:rescue_strategy_for_self)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
test 'handles RestClient server error gracefully' do
|
|
205
|
+
# Create mock response for RestClient exception
|
|
206
|
+
response = mock('response')
|
|
207
|
+
response.stubs(:code).returns(500)
|
|
208
|
+
response.stubs(:body).returns('Server error')
|
|
209
|
+
|
|
210
|
+
# Stub upload_file to raise server error
|
|
211
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
212
|
+
.raises(RestClient::InternalServerError.new(response))
|
|
213
|
+
|
|
214
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
215
|
+
action.expects(:action_subject).with(@organization)
|
|
216
|
+
plan_action(action, @filename, @organization.id)
|
|
217
|
+
|
|
218
|
+
# Should raise the error (handled by Dynflow retry mechanism)
|
|
219
|
+
assert_raises(RestClient::InternalServerError) do
|
|
220
|
+
action.send(:try_execute)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
test 'handles RestClient timeout gracefully' do
|
|
225
|
+
# Stub upload_file to raise timeout (Timeout exception doesn't need response object)
|
|
226
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
227
|
+
.raises(RestClient::Exceptions::Timeout.new)
|
|
228
|
+
|
|
229
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
230
|
+
action.expects(:action_subject).with(@organization)
|
|
231
|
+
plan_action(action, @filename, @organization.id)
|
|
232
|
+
|
|
233
|
+
# Should raise the error (handled by Dynflow retry mechanism via ExponentialBackoff)
|
|
234
|
+
assert_raises(RestClient::Exceptions::Timeout) do
|
|
235
|
+
action.send(:try_execute)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
test 'uses proxy configuration from ForemanRhCloud' do
|
|
240
|
+
proxy_url = 'http://proxy.example.com:8080'
|
|
241
|
+
ForemanRhCloud.stubs(:transformed_http_proxy_string).returns(proxy_url)
|
|
242
|
+
|
|
243
|
+
# Create test file
|
|
244
|
+
FileUtils.mkdir_p(File.dirname(@filename))
|
|
245
|
+
FileUtils.touch(@filename)
|
|
246
|
+
|
|
247
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
248
|
+
action.expects(:action_subject).with(@organization)
|
|
249
|
+
plan_action(action, @filename, @organization.id)
|
|
250
|
+
|
|
251
|
+
# Mock response
|
|
252
|
+
response = mock('response')
|
|
253
|
+
response.stubs(:code).returns(200)
|
|
254
|
+
|
|
255
|
+
# Verify execute_cloud_request is called (which handles proxy)
|
|
256
|
+
# We can't test the actual proxy parameters because CloudRequest concern
|
|
257
|
+
# merges them internally, but we can verify the method is called
|
|
258
|
+
action.expects(:execute_cloud_request).returns(response)
|
|
259
|
+
|
|
260
|
+
# Stub upload_file to call execute_cloud_request (avoiding SSL cert creation issues)
|
|
261
|
+
action.stubs(:upload_file).returns(nil)
|
|
262
|
+
|
|
263
|
+
# Manually call upload_file expectations in the test
|
|
264
|
+
# This simulates what would happen during actual execution
|
|
265
|
+
action.send(:execute_cloud_request,
|
|
266
|
+
method: :post,
|
|
267
|
+
url: ForemanInventoryUpload.upload_url,
|
|
268
|
+
payload: { multipart: true },
|
|
269
|
+
headers: { 'X-Org-Id' => @organization.label })
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
test 'file cleanup when upload aborted due to missing certificate' do
|
|
273
|
+
# Remove certificate from organization
|
|
274
|
+
Organization.any_instance.stubs(:owner_details).returns({})
|
|
275
|
+
|
|
276
|
+
# Create a real test file to verify it's not moved
|
|
277
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
278
|
+
test_file = File.join(@uploads_folder, 'test_file_for_cleanup.tar.xz')
|
|
279
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
280
|
+
FileUtils.touch(test_file)
|
|
281
|
+
|
|
282
|
+
begin
|
|
283
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
284
|
+
action.expects(:action_subject).with(@organization)
|
|
285
|
+
plan_action(action, test_file, @organization.id)
|
|
286
|
+
|
|
287
|
+
# Execute the action
|
|
288
|
+
action.send(:try_execute)
|
|
289
|
+
|
|
290
|
+
# Verify file still exists (not moved or deleted)
|
|
291
|
+
assert File.exist?(test_file), "File should remain when upload is aborted"
|
|
292
|
+
ensure
|
|
293
|
+
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
test 'file cleanup when upload aborted due to disconnected mode' do
|
|
298
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
299
|
+
|
|
300
|
+
# Create a real test file
|
|
301
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
302
|
+
test_file = File.join(@uploads_folder, 'test_file_disconnected.tar.xz')
|
|
303
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
304
|
+
FileUtils.touch(test_file)
|
|
305
|
+
|
|
306
|
+
begin
|
|
307
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
308
|
+
action.expects(:action_subject).with(@organization)
|
|
309
|
+
plan_action(action, test_file, @organization.id)
|
|
310
|
+
|
|
311
|
+
# Execute the action
|
|
312
|
+
action.send(:try_execute)
|
|
313
|
+
|
|
314
|
+
# Verify file still exists
|
|
315
|
+
assert File.exist?(test_file), "File should remain when connection is disabled"
|
|
316
|
+
ensure
|
|
317
|
+
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
test 'overwrites existing done file and logs warning' do
|
|
322
|
+
# Prepare new report file in uploads folder
|
|
323
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
324
|
+
source_file = File.join(@uploads_folder, 'overwrite_done_file.tar.xz')
|
|
325
|
+
new_report_content = 'new report content'
|
|
326
|
+
File.write(source_file, new_report_content)
|
|
327
|
+
|
|
328
|
+
# Pre-create done file with old content
|
|
329
|
+
done_file_path = ForemanInventoryUpload.done_file_path(File.basename(source_file))
|
|
330
|
+
FileUtils.mkdir_p(File.dirname(done_file_path))
|
|
331
|
+
old_report_content = 'old report content'
|
|
332
|
+
File.write(done_file_path, old_report_content)
|
|
333
|
+
|
|
334
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
335
|
+
action.expects(:action_subject).with(@organization)
|
|
336
|
+
|
|
337
|
+
# Stub upload_file to avoid actual HTTP upload
|
|
338
|
+
action.stubs(:upload_file).returns(nil)
|
|
339
|
+
|
|
340
|
+
# Expect a warning when overwriting the existing done file
|
|
341
|
+
action.expects(:logger).at_least_once.returns(mock_logger = mock('logger'))
|
|
342
|
+
mock_logger.expects(:warn).with(regexp_matches(/already exists.*overwriting/i))
|
|
343
|
+
mock_logger.stubs(:debug)
|
|
344
|
+
|
|
345
|
+
plan_action(action, source_file, @organization.id)
|
|
346
|
+
|
|
347
|
+
# Execute the action (which will call move_to_done_folder)
|
|
348
|
+
action.send(:try_execute)
|
|
349
|
+
|
|
350
|
+
# Done file should now contain the new report content
|
|
351
|
+
assert_equal new_report_content, File.read(done_file_path)
|
|
352
|
+
ensure
|
|
353
|
+
FileUtils.rm_f(source_file) if defined?(source_file) && source_file
|
|
354
|
+
FileUtils.rm_f(done_file_path) if defined?(done_file_path) && done_file_path
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
test 'FileUpload wrapper delegates to file object' do
|
|
358
|
+
# Create test file
|
|
359
|
+
FileUtils.mkdir_p(File.dirname(@filename))
|
|
360
|
+
FileUtils.touch(@filename)
|
|
361
|
+
|
|
362
|
+
file = File.open(@filename, 'rb')
|
|
363
|
+
begin
|
|
364
|
+
wrapped = ForemanInventoryUpload::Async::UploadReportDirectJob::FileUpload.new(
|
|
365
|
+
file,
|
|
366
|
+
content_type: 'application/test'
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
assert_equal 'application/test', wrapped.content_type
|
|
370
|
+
assert_equal file.path, wrapped.path
|
|
371
|
+
assert_respond_to wrapped, :read
|
|
372
|
+
assert_respond_to wrapped, :close
|
|
373
|
+
ensure
|
|
374
|
+
file.close
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
test 'FileUpload wrapper provides content_type for RestClient' do
|
|
379
|
+
# Create test file
|
|
380
|
+
FileUtils.mkdir_p(File.dirname(@filename))
|
|
381
|
+
FileUtils.touch(@filename)
|
|
382
|
+
|
|
383
|
+
file = File.open(@filename, 'rb')
|
|
384
|
+
begin
|
|
385
|
+
wrapped = ForemanInventoryUpload::Async::UploadReportDirectJob::FileUpload.new(
|
|
386
|
+
file,
|
|
387
|
+
content_type: 'application/vnd.redhat.qpc.tar+tgz'
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# RestClient checks for these methods
|
|
391
|
+
assert_respond_to wrapped, :read
|
|
392
|
+
assert_respond_to wrapped, :path
|
|
393
|
+
assert_respond_to wrapped, :content_type
|
|
394
|
+
assert_equal 'application/vnd.redhat.qpc.tar+tgz', wrapped.content_type
|
|
395
|
+
ensure
|
|
396
|
+
file.close
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
@@ -9,6 +9,8 @@ class RhCloudPermissionsTest < ActiveSupport::TestCase
|
|
|
9
9
|
[
|
|
10
10
|
'insights_cloud/api/machine_telemetries/forward_request',
|
|
11
11
|
'insights_cloud/api/machine_telemetries/branch_info',
|
|
12
|
+
'api/v2/rh_cloud/foreman_inventory_upload/api/tasks/current',
|
|
13
|
+
'api/v2/rh_cloud/foreman_inventory_upload/api/tasks/history',
|
|
12
14
|
],
|
|
13
15
|
skip_patterns: [/^(?!foreman_inventory_upload|insights_cloud|.*rh_cloud).*/]
|
|
14
16
|
) # include only plugin paths
|
|
@@ -3,18 +3,18 @@ import { noop } from 'foremanReact/common/helpers';
|
|
|
3
3
|
export const accounts = {
|
|
4
4
|
Account1: {
|
|
5
5
|
id: 1,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
uploaded_status: 'running',
|
|
7
|
+
generated_status: 'running',
|
|
8
8
|
},
|
|
9
9
|
Account2: {
|
|
10
10
|
id: 2,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
uploaded_status: 'unknown',
|
|
12
|
+
generated_status: 'failure',
|
|
13
13
|
},
|
|
14
14
|
Account3: {
|
|
15
15
|
id: 3,
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
uploaded_status: 'success',
|
|
17
|
+
generated_status: 'running',
|
|
18
18
|
},
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import { isEmpty } from 'lodash';
|
|
3
3
|
import { noop } from 'foremanReact/common/helpers';
|
|
4
4
|
import { Accordion } from '@patternfly/react-core';
|
|
@@ -10,42 +10,57 @@ import EmptyResults from './Components/EmptyResults';
|
|
|
10
10
|
import { filterAccounts } from './AccountListHelper';
|
|
11
11
|
import './accountList.scss';
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const AccountList = ({
|
|
14
|
+
accounts,
|
|
15
|
+
error,
|
|
16
|
+
filterTerm,
|
|
17
|
+
fetchAccountsStatus,
|
|
18
|
+
startAccountStatusPolling,
|
|
19
|
+
stopAccountStatusPolling,
|
|
20
|
+
pollingProcessID,
|
|
21
|
+
}) => {
|
|
22
|
+
useEffect(() => {
|
|
16
23
|
fetchAccountsStatus();
|
|
17
|
-
const
|
|
18
|
-
startAccountStatusPolling(
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
componentWillUnmount() {
|
|
22
|
-
const { stopAccountStatusPolling, pollingProcessID } = this.props;
|
|
23
|
-
stopAccountStatusPolling(pollingProcessID);
|
|
24
|
-
}
|
|
24
|
+
const pollingID = setInterval(fetchAccountsStatus, 2000);
|
|
25
|
+
startAccountStatusPolling(pollingID);
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
return () => {
|
|
28
|
+
stopAccountStatusPolling(pollingID);
|
|
29
|
+
};
|
|
30
|
+
}, [
|
|
31
|
+
fetchAccountsStatus,
|
|
32
|
+
startAccountStatusPolling,
|
|
33
|
+
stopAccountStatusPolling,
|
|
34
|
+
]);
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
return <ErrorState error={error} />;
|
|
32
|
-
}
|
|
36
|
+
const filteredAccount = filterAccounts(accounts, filterTerm);
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
if (error) {
|
|
39
|
+
return <ErrorState error={error} />;
|
|
40
|
+
}
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
if (isEmpty(accounts)) {
|
|
43
|
+
return <EmptyState />;
|
|
44
|
+
}
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return <ListItem key={index} label={label} account={account} />;
|
|
45
|
-
});
|
|
46
|
-
return <Accordion className="account-list">{items}</Accordion>;
|
|
46
|
+
if (isEmpty(filteredAccount)) {
|
|
47
|
+
return <EmptyResults />;
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
|
|
50
|
+
const items = Object.keys(filteredAccount).map((label, index) => {
|
|
51
|
+
const account = accounts[label];
|
|
52
|
+
return (
|
|
53
|
+
<ListItem
|
|
54
|
+
key={label}
|
|
55
|
+
label={label}
|
|
56
|
+
account={account}
|
|
57
|
+
defaultExpanded={index === 0}
|
|
58
|
+
onTaskStart={fetchAccountsStatus}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
return <Accordion className="account-list">{items}</Accordion>;
|
|
63
|
+
};
|
|
49
64
|
|
|
50
65
|
AccountList.propTypes = {
|
|
51
66
|
fetchAccountsStatus: PropTypes.func,
|
|
@@ -53,8 +68,8 @@ AccountList.propTypes = {
|
|
|
53
68
|
stopAccountStatusPolling: PropTypes.func,
|
|
54
69
|
pollingProcessID: PropTypes.number,
|
|
55
70
|
account: PropTypes.shape({
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
generated_status: PropTypes.string,
|
|
72
|
+
uploaded_status: PropTypes.string,
|
|
58
73
|
}),
|
|
59
74
|
accounts: PropTypes.object,
|
|
60
75
|
error: PropTypes.string,
|
|
@@ -67,8 +82,8 @@ AccountList.defaultProps = {
|
|
|
67
82
|
stopAccountStatusPolling: noop,
|
|
68
83
|
pollingProcessID: 0,
|
|
69
84
|
account: {
|
|
70
|
-
|
|
71
|
-
|
|
85
|
+
generated_status: 'unknown',
|
|
86
|
+
uploaded_status: 'unknown',
|
|
72
87
|
},
|
|
73
88
|
accounts: {},
|
|
74
89
|
error: '',
|
|
@@ -46,10 +46,10 @@ export const restartProcess = (accountID, activeTab) => async dispatch => {
|
|
|
46
46
|
|
|
47
47
|
if (activeTab === 'uploading') {
|
|
48
48
|
processController = 'uploads';
|
|
49
|
-
processStatusName = '
|
|
49
|
+
processStatusName = 'uploaded_status';
|
|
50
50
|
} else {
|
|
51
51
|
processController = 'reports';
|
|
52
|
-
processStatusName = '
|
|
52
|
+
processStatusName = 'generated_status';
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
try {
|
data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export const props = {
|
|
2
2
|
label: 'test',
|
|
3
3
|
account: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
},
|
|
4
|
+
generated_status: 'unknown',
|
|
5
|
+
uploaded_status: 'unknown',
|
|
6
|
+
id: 1,
|
|
7
|
+
report_file_paths: [],
|
|
9
8
|
},
|
|
10
9
|
};
|
|
@@ -10,8 +10,8 @@ import PropTypes from 'prop-types';
|
|
|
10
10
|
import ListItemStatus from '../ListItemStatus';
|
|
11
11
|
import Dashboard from '../../../Dashboard';
|
|
12
12
|
|
|
13
|
-
const ListItem = ({ label, account }) => {
|
|
14
|
-
const [isExpanded, setIsExpanded] = useState(
|
|
13
|
+
const ListItem = ({ label, account, defaultExpanded, onTaskStart }) => {
|
|
14
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
15
15
|
return (
|
|
16
16
|
<AccordionItem>
|
|
17
17
|
<AccordionToggle
|
|
@@ -30,7 +30,11 @@ const ListItem = ({ label, account }) => {
|
|
|
30
30
|
<ListItemStatus key={`${label}_status`} account={account} />
|
|
31
31
|
</AccordionToggle>
|
|
32
32
|
<AccordionContent isHidden={!isExpanded}>
|
|
33
|
-
<Dashboard
|
|
33
|
+
<Dashboard
|
|
34
|
+
accountID={account.id}
|
|
35
|
+
account={account}
|
|
36
|
+
onTaskStart={onTaskStart}
|
|
37
|
+
/>
|
|
34
38
|
</AccordionContent>
|
|
35
39
|
</AccordionItem>
|
|
36
40
|
);
|
|
@@ -39,18 +43,22 @@ const ListItem = ({ label, account }) => {
|
|
|
39
43
|
ListItem.propTypes = {
|
|
40
44
|
label: PropTypes.string.isRequired,
|
|
41
45
|
account: PropTypes.shape({
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
generated_status: PropTypes.string,
|
|
47
|
+
uploaded_status: PropTypes.string,
|
|
44
48
|
id: PropTypes.number,
|
|
45
49
|
}),
|
|
50
|
+
defaultExpanded: PropTypes.bool,
|
|
51
|
+
onTaskStart: PropTypes.func,
|
|
46
52
|
};
|
|
47
53
|
|
|
48
54
|
ListItem.defaultProps = {
|
|
49
55
|
account: {
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
generated_status: 'unknown',
|
|
57
|
+
uploaded_status: 'unknown',
|
|
52
58
|
id: 0,
|
|
53
59
|
},
|
|
60
|
+
defaultExpanded: false,
|
|
61
|
+
onTaskStart: null,
|
|
54
62
|
};
|
|
55
63
|
|
|
56
64
|
export default ListItem;
|
|
@@ -18,11 +18,10 @@ exports[`ListItem rendering render with Props 1`] = `
|
|
|
18
18
|
<ListItemStatus
|
|
19
19
|
account={
|
|
20
20
|
Object {
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
21
|
+
"generated_status": "unknown",
|
|
22
|
+
"id": 1,
|
|
23
|
+
"report_file_paths": Array [],
|
|
24
|
+
"uploaded_status": "unknown",
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
key="test_status"
|
|
@@ -31,16 +30,17 @@ exports[`ListItem rendering render with Props 1`] = `
|
|
|
31
30
|
<AccordionContent
|
|
32
31
|
isHidden={true}
|
|
33
32
|
>
|
|
34
|
-
<
|
|
33
|
+
<Dashboard
|
|
35
34
|
account={
|
|
36
35
|
Object {
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
36
|
+
"generated_status": "unknown",
|
|
37
|
+
"id": 1,
|
|
38
|
+
"report_file_paths": Array [],
|
|
39
|
+
"uploaded_status": "unknown",
|
|
42
40
|
}
|
|
43
41
|
}
|
|
42
|
+
accountID={1}
|
|
43
|
+
onTaskStart={null}
|
|
44
44
|
/>
|
|
45
45
|
</AccordionContent>
|
|
46
46
|
</AccordionItem>
|