foreman_rh_cloud 13.0.9 → 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/upload_report_direct_job.rb +28 -57
- data/lib/foreman_rh_cloud/plugin.rb +1 -0
- data/lib/foreman_rh_cloud/version.rb +1 -1
- 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/single_host_report_job_test.rb +36 -54
- data/test/jobs/upload_report_direct_job_test.rb +132 -132
- 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 +2 -2
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +15 -9
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +6 -5
- 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 +36 -132
- 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/__tests__/__snapshots__/PageTitle.test.js.snap +2 -2
- 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/RemediationModal/RemediationHelpers.js +1 -2
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +2 -4
- data/webpack/__mocks__/foremanReact/components/common/dates/RelativeDateTime.js +14 -0
- data/webpack/__tests__/ForemanRhCloudHelpers.test.js +5 -1
- metadata +10 -61
- 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/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/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/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
|
@@ -28,22 +28,15 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
28
28
|
},
|
|
29
29
|
}
|
|
30
30
|
Organization.any_instance.stubs(:owner_details).returns(@cert_data)
|
|
31
|
-
|
|
32
|
-
# Clear task output
|
|
33
|
-
TaskOutputLine.delete_all
|
|
34
|
-
TaskOutputStatus.delete_all
|
|
35
31
|
end
|
|
36
32
|
|
|
37
33
|
test 'plan sets input correctly' do
|
|
38
|
-
action =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@organization.id
|
|
42
|
-
)
|
|
34
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
35
|
+
action.expects(:action_subject).with(@organization)
|
|
36
|
+
plan_action(action, @filename, @organization.id)
|
|
43
37
|
|
|
44
38
|
assert_equal @filename, action.input[:filename]
|
|
45
39
|
assert_equal @organization.id, action.input[:organization_id]
|
|
46
|
-
assert_equal "upload_for_#{@organization.id}", action.input[:instance_label]
|
|
47
40
|
end
|
|
48
41
|
|
|
49
42
|
test 'output_label generates correct label' do
|
|
@@ -54,11 +47,9 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
54
47
|
test 'uses manifest certificate in regular mode' do
|
|
55
48
|
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
56
49
|
|
|
57
|
-
action =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@organization.id
|
|
61
|
-
)
|
|
50
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
51
|
+
action.expects(:action_subject).with(@organization)
|
|
52
|
+
plan_action(action, @filename, @organization.id)
|
|
62
53
|
|
|
63
54
|
cert = action.send(:certificate)
|
|
64
55
|
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
@@ -66,11 +57,9 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
66
57
|
end
|
|
67
58
|
|
|
68
59
|
test 'manifest_certificate extracts from organization owner_details' do
|
|
69
|
-
action =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@organization.id
|
|
73
|
-
)
|
|
60
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
61
|
+
action.expects(:action_subject).with(@organization)
|
|
62
|
+
plan_action(action, @filename, @organization.id)
|
|
74
63
|
|
|
75
64
|
cert = action.send(:manifest_certificate)
|
|
76
65
|
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
@@ -79,14 +68,14 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
79
68
|
|
|
80
69
|
test 'uses foreman certificate in IoP mode' do
|
|
81
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)
|
|
82
73
|
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
83
74
|
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
84
75
|
|
|
85
|
-
action =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@organization.id
|
|
89
|
-
)
|
|
76
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
77
|
+
action.expects(:action_subject).with(@organization)
|
|
78
|
+
plan_action(action, @filename, @organization.id)
|
|
90
79
|
|
|
91
80
|
cert = action.send(:foreman_certificate)
|
|
92
81
|
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
@@ -96,11 +85,9 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
96
85
|
test 'certificate method returns manifest cert in regular mode' do
|
|
97
86
|
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
98
87
|
|
|
99
|
-
action =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
@organization.id
|
|
103
|
-
)
|
|
88
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
89
|
+
action.expects(:action_subject).with(@organization)
|
|
90
|
+
plan_action(action, @filename, @organization.id)
|
|
104
91
|
|
|
105
92
|
cert = action.send(:certificate)
|
|
106
93
|
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
@@ -109,36 +96,67 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
109
96
|
|
|
110
97
|
test 'certificate method returns foreman cert in IoP mode' do
|
|
111
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)
|
|
112
103
|
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
113
104
|
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
114
105
|
|
|
115
|
-
action =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@organization.id
|
|
119
|
-
)
|
|
106
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
107
|
+
action.expects(:action_subject).with(@organization)
|
|
108
|
+
plan_action(action, @filename, @organization.id)
|
|
120
109
|
|
|
121
110
|
cert = action.send(:certificate)
|
|
122
111
|
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
123
112
|
assert_equal 'FOREMAN KEY', cert[:key]
|
|
124
113
|
end
|
|
125
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
|
+
|
|
126
148
|
test 'filename returns input filename' do
|
|
127
|
-
action =
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
@organization.id
|
|
131
|
-
)
|
|
149
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
150
|
+
action.expects(:action_subject).with(@organization)
|
|
151
|
+
plan_action(action, @filename, @organization.id)
|
|
132
152
|
|
|
133
153
|
assert_equal @filename, action.send(:filename)
|
|
134
154
|
end
|
|
135
155
|
|
|
136
156
|
test 'organization returns Organization from input organization_id' do
|
|
137
|
-
action =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
@organization.id
|
|
141
|
-
)
|
|
157
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
158
|
+
action.expects(:action_subject).with(@organization)
|
|
159
|
+
plan_action(action, @filename, @organization.id)
|
|
142
160
|
|
|
143
161
|
org = action.send(:organization)
|
|
144
162
|
assert_equal @organization.id, org.id
|
|
@@ -147,11 +165,9 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
147
165
|
test 'content_disconnected? returns true when subscription_connection_enabled is false' do
|
|
148
166
|
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
149
167
|
|
|
150
|
-
action =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
@organization.id
|
|
154
|
-
)
|
|
168
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
169
|
+
action.expects(:action_subject).with(@organization)
|
|
170
|
+
plan_action(action, @filename, @organization.id)
|
|
155
171
|
|
|
156
172
|
assert action.send(:content_disconnected?)
|
|
157
173
|
end
|
|
@@ -159,48 +175,28 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
159
175
|
test 'content_disconnected? returns false when subscription_connection_enabled is true' do
|
|
160
176
|
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
161
177
|
|
|
162
|
-
action =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
@organization.id
|
|
166
|
-
)
|
|
178
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
179
|
+
action.expects(:action_subject).with(@organization)
|
|
180
|
+
plan_action(action, @filename, @organization.id)
|
|
167
181
|
|
|
168
182
|
refute action.send(:content_disconnected?)
|
|
169
183
|
end
|
|
170
184
|
|
|
171
|
-
test '
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
@filename,
|
|
175
|
-
@organization.id
|
|
176
|
-
)
|
|
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)
|
|
177
188
|
|
|
178
|
-
|
|
179
|
-
|
|
189
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
190
|
+
action.expects(:action_subject).with(@organization)
|
|
191
|
+
plan_action(action, @filename, @organization.id)
|
|
180
192
|
|
|
181
|
-
|
|
182
|
-
# Create some old output
|
|
183
|
-
old_label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
184
|
-
TaskOutputLine.create!(label: old_label, line: 'old line')
|
|
185
|
-
TaskOutputStatus.create!(label: old_label, status: 'old status')
|
|
186
|
-
|
|
187
|
-
create_and_plan_action(
|
|
188
|
-
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
189
|
-
@filename,
|
|
190
|
-
@organization.id
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
# Verify old output was cleared
|
|
194
|
-
assert_equal 0, TaskOutputLine.where(label: old_label).count
|
|
195
|
-
assert_equal 0, TaskOutputStatus.where(label: old_label).count
|
|
193
|
+
refute action.send(:content_disconnected?)
|
|
196
194
|
end
|
|
197
195
|
|
|
198
196
|
test 'rescue_strategy_for_self returns Fail strategy' do
|
|
199
|
-
action =
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
@organization.id
|
|
203
|
-
)
|
|
197
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
198
|
+
action.expects(:action_subject).with(@organization)
|
|
199
|
+
plan_action(action, @filename, @organization.id)
|
|
204
200
|
|
|
205
201
|
assert_equal Dynflow::Action::Rescue::Fail, action.send(:rescue_strategy_for_self)
|
|
206
202
|
end
|
|
@@ -215,21 +211,14 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
215
211
|
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
216
212
|
.raises(RestClient::InternalServerError.new(response))
|
|
217
213
|
|
|
218
|
-
action =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
@organization.id
|
|
222
|
-
)
|
|
214
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
215
|
+
action.expects(:action_subject).with(@organization)
|
|
216
|
+
plan_action(action, @filename, @organization.id)
|
|
223
217
|
|
|
224
218
|
# Should raise the error (handled by Dynflow retry mechanism)
|
|
225
219
|
assert_raises(RestClient::InternalServerError) do
|
|
226
220
|
action.send(:try_execute)
|
|
227
221
|
end
|
|
228
|
-
|
|
229
|
-
# Verify progress output shows error
|
|
230
|
-
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
231
|
-
output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
|
|
232
|
-
assert_match(/Upload failed/, output)
|
|
233
222
|
end
|
|
234
223
|
|
|
235
224
|
test 'handles RestClient timeout gracefully' do
|
|
@@ -237,21 +226,14 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
237
226
|
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
238
227
|
.raises(RestClient::Exceptions::Timeout.new)
|
|
239
228
|
|
|
240
|
-
action =
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
@organization.id
|
|
244
|
-
)
|
|
229
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
230
|
+
action.expects(:action_subject).with(@organization)
|
|
231
|
+
plan_action(action, @filename, @organization.id)
|
|
245
232
|
|
|
246
233
|
# Should raise the error (handled by Dynflow retry mechanism via ExponentialBackoff)
|
|
247
234
|
assert_raises(RestClient::Exceptions::Timeout) do
|
|
248
235
|
action.send(:try_execute)
|
|
249
236
|
end
|
|
250
|
-
|
|
251
|
-
# Verify progress output shows error
|
|
252
|
-
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
253
|
-
output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
|
|
254
|
-
assert_match(/Upload failed/, output)
|
|
255
237
|
end
|
|
256
238
|
|
|
257
239
|
test 'uses proxy configuration from ForemanRhCloud' do
|
|
@@ -262,11 +244,9 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
262
244
|
FileUtils.mkdir_p(File.dirname(@filename))
|
|
263
245
|
FileUtils.touch(@filename)
|
|
264
246
|
|
|
265
|
-
action =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
@organization.id
|
|
269
|
-
)
|
|
247
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
248
|
+
action.expects(:action_subject).with(@organization)
|
|
249
|
+
plan_action(action, @filename, @organization.id)
|
|
270
250
|
|
|
271
251
|
# Mock response
|
|
272
252
|
response = mock('response')
|
|
@@ -296,29 +276,19 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
296
276
|
# Create a real test file to verify it's not moved
|
|
297
277
|
FileUtils.mkdir_p(@uploads_folder)
|
|
298
278
|
test_file = File.join(@uploads_folder, 'test_file_for_cleanup.tar.xz')
|
|
279
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
299
280
|
FileUtils.touch(test_file)
|
|
300
281
|
|
|
301
282
|
begin
|
|
302
|
-
action =
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
@organization.id
|
|
306
|
-
)
|
|
283
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
284
|
+
action.expects(:action_subject).with(@organization)
|
|
285
|
+
plan_action(action, test_file, @organization.id)
|
|
307
286
|
|
|
308
287
|
# Execute the action
|
|
309
288
|
action.send(:try_execute)
|
|
310
289
|
|
|
311
290
|
# Verify file still exists (not moved or deleted)
|
|
312
291
|
assert File.exist?(test_file), "File should remain when upload is aborted"
|
|
313
|
-
|
|
314
|
-
# Verify progress output mentions missing certificate
|
|
315
|
-
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
316
|
-
output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
|
|
317
|
-
assert_match(/Skipping organization.*no candlepin certificate/, output)
|
|
318
|
-
|
|
319
|
-
# Verify status indicates abortion
|
|
320
|
-
status = ForemanInventoryUpload::Async::ProgressOutput.get(label).status
|
|
321
|
-
assert_match(/exit 1/, status)
|
|
322
292
|
ensure
|
|
323
293
|
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
324
294
|
end
|
|
@@ -330,30 +300,60 @@ class UploadReportDirectJobTest < ActiveSupport::TestCase
|
|
|
330
300
|
# Create a real test file
|
|
331
301
|
FileUtils.mkdir_p(@uploads_folder)
|
|
332
302
|
test_file = File.join(@uploads_folder, 'test_file_disconnected.tar.xz')
|
|
303
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
333
304
|
FileUtils.touch(test_file)
|
|
334
305
|
|
|
335
306
|
begin
|
|
336
|
-
action =
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
@organization.id
|
|
340
|
-
)
|
|
307
|
+
action = create_action(ForemanInventoryUpload::Async::UploadReportDirectJob)
|
|
308
|
+
action.expects(:action_subject).with(@organization)
|
|
309
|
+
plan_action(action, test_file, @organization.id)
|
|
341
310
|
|
|
342
311
|
# Execute the action
|
|
343
312
|
action.send(:try_execute)
|
|
344
313
|
|
|
345
314
|
# Verify file still exists
|
|
346
315
|
assert File.exist?(test_file), "File should remain when connection is disabled"
|
|
347
|
-
|
|
348
|
-
# Verify progress output
|
|
349
|
-
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
350
|
-
output = ForemanInventoryUpload::Async::ProgressOutput.get(label).full_output
|
|
351
|
-
assert_match(/connection to Insights is not enabled/, output)
|
|
352
316
|
ensure
|
|
353
317
|
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
354
318
|
end
|
|
355
319
|
end
|
|
356
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
357
|
test 'FileUpload wrapper delegates to file object' do
|
|
358
358
|
# Create test file
|
|
359
359
|
FileUtils.mkdir_p(File.dirname(@filename))
|
|
@@ -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 {
|
|
@@ -10,10 +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(
|
|
15
|
-
const accountId = account?.id ?? 0;
|
|
16
|
-
|
|
13
|
+
const ListItem = ({ label, account, defaultExpanded, onTaskStart }) => {
|
|
14
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
17
15
|
return (
|
|
18
16
|
<AccordionItem>
|
|
19
17
|
<AccordionToggle
|
|
@@ -32,7 +30,11 @@ const ListItem = ({ label, account = {} }) => {
|
|
|
32
30
|
<ListItemStatus key={`${label}_status`} account={account} />
|
|
33
31
|
</AccordionToggle>
|
|
34
32
|
<AccordionContent isHidden={!isExpanded}>
|
|
35
|
-
<Dashboard
|
|
33
|
+
<Dashboard
|
|
34
|
+
accountID={account.id}
|
|
35
|
+
account={account}
|
|
36
|
+
onTaskStart={onTaskStart}
|
|
37
|
+
/>
|
|
36
38
|
</AccordionContent>
|
|
37
39
|
</AccordionItem>
|
|
38
40
|
);
|
|
@@ -41,18 +43,22 @@ const ListItem = ({ label, account = {} }) => {
|
|
|
41
43
|
ListItem.propTypes = {
|
|
42
44
|
label: PropTypes.string.isRequired,
|
|
43
45
|
account: PropTypes.shape({
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
generated_status: PropTypes.string,
|
|
47
|
+
uploaded_status: PropTypes.string,
|
|
46
48
|
id: PropTypes.number,
|
|
47
49
|
}),
|
|
50
|
+
defaultExpanded: PropTypes.bool,
|
|
51
|
+
onTaskStart: PropTypes.func,
|
|
48
52
|
};
|
|
49
53
|
|
|
50
54
|
ListItem.defaultProps = {
|
|
51
55
|
account: {
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
generated_status: 'unknown',
|
|
57
|
+
uploaded_status: 'unknown',
|
|
54
58
|
id: 0,
|
|
55
59
|
},
|
|
60
|
+
defaultExpanded: false,
|
|
61
|
+
onTaskStart: null,
|
|
56
62
|
};
|
|
57
63
|
|
|
58
64
|
export default ListItem;
|