foreman_rh_cloud 13.0.8 → 13.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/foreman_inventory_upload/accounts_controller.rb +1 -1
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +1 -1
- data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +1 -23
- data/lib/foreman_inventory_upload/async/upload_report_direct_job.rb +200 -0
- data/lib/foreman_inventory_upload.rb +0 -4
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +0 -2
- data/package.json +1 -1
- data/test/controllers/accounts_controller_test.rb +1 -1
- data/test/controllers/uploads_controller_test.rb +1 -1
- data/test/jobs/queue_for_upload_job_test.rb +1 -12
- data/test/jobs/upload_report_direct_job_test.rb +399 -0
- data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js +4 -5
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +4 -2
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +9 -10
- data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +4 -1
- 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/components/ToolbarButtons/ToolbarButtons.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +69 -51
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +11 -19
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +77 -22
- metadata +4 -8
- 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/jobs/upload_report_job_test.rb +0 -38
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +0 -36
- 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
|
+
|
|
32
|
+
# Clear task output
|
|
33
|
+
TaskOutputLine.delete_all
|
|
34
|
+
TaskOutputStatus.delete_all
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test 'plan sets input correctly' do
|
|
38
|
+
action = create_and_plan_action(
|
|
39
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
40
|
+
@filename,
|
|
41
|
+
@organization.id
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
assert_equal @filename, action.input[:filename]
|
|
45
|
+
assert_equal @organization.id, action.input[:organization_id]
|
|
46
|
+
assert_equal "upload_for_#{@organization.id}", action.input[:instance_label]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
test 'output_label generates correct label' do
|
|
50
|
+
label = ForemanInventoryUpload::Async::UploadReportDirectJob.output_label(@organization.id)
|
|
51
|
+
assert_equal "upload_for_#{@organization.id}", label
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
test 'uses manifest certificate in regular mode' do
|
|
55
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
56
|
+
|
|
57
|
+
action = create_and_plan_action(
|
|
58
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
59
|
+
@filename,
|
|
60
|
+
@organization.id
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
cert = action.send(:certificate)
|
|
64
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
65
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test 'manifest_certificate extracts from organization owner_details' do
|
|
69
|
+
action = create_and_plan_action(
|
|
70
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
71
|
+
@filename,
|
|
72
|
+
@organization.id
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
cert = action.send(:manifest_certificate)
|
|
76
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
77
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test 'uses foreman certificate in IoP mode' do
|
|
81
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
82
|
+
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
83
|
+
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
84
|
+
|
|
85
|
+
action = create_and_plan_action(
|
|
86
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
87
|
+
@filename,
|
|
88
|
+
@organization.id
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
cert = action.send(:foreman_certificate)
|
|
92
|
+
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
93
|
+
assert_equal 'FOREMAN KEY', cert[:key]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test 'certificate method returns manifest cert in regular mode' do
|
|
97
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
98
|
+
|
|
99
|
+
action = create_and_plan_action(
|
|
100
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
101
|
+
@filename,
|
|
102
|
+
@organization.id
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
cert = action.send(:certificate)
|
|
106
|
+
assert_equal 'FAKE CERTIFICATE', cert[:cert]
|
|
107
|
+
assert_equal 'FAKE KEY', cert[:key]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
test 'certificate method returns foreman cert in IoP mode' do
|
|
111
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
112
|
+
File.stubs(:read).with('/fake/cert.pem').returns('FOREMAN CERTIFICATE')
|
|
113
|
+
File.stubs(:read).with('/fake/key.pem').returns('FOREMAN KEY')
|
|
114
|
+
|
|
115
|
+
action = create_and_plan_action(
|
|
116
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
117
|
+
@filename,
|
|
118
|
+
@organization.id
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
cert = action.send(:certificate)
|
|
122
|
+
assert_equal 'FOREMAN CERTIFICATE', cert[:cert]
|
|
123
|
+
assert_equal 'FOREMAN KEY', cert[:key]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
test 'filename returns input filename' do
|
|
127
|
+
action = create_and_plan_action(
|
|
128
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
129
|
+
@filename,
|
|
130
|
+
@organization.id
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
assert_equal @filename, action.send(:filename)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test 'organization returns Organization from input organization_id' do
|
|
137
|
+
action = create_and_plan_action(
|
|
138
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
139
|
+
@filename,
|
|
140
|
+
@organization.id
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
org = action.send(:organization)
|
|
144
|
+
assert_equal @organization.id, org.id
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
test 'content_disconnected? returns true when subscription_connection_enabled is false' do
|
|
148
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
149
|
+
|
|
150
|
+
action = create_and_plan_action(
|
|
151
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
152
|
+
@filename,
|
|
153
|
+
@organization.id
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
assert action.send(:content_disconnected?)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
test 'content_disconnected? returns false when subscription_connection_enabled is true' do
|
|
160
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
161
|
+
|
|
162
|
+
action = create_and_plan_action(
|
|
163
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
164
|
+
@filename,
|
|
165
|
+
@organization.id
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
refute action.send(:content_disconnected?)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
test 'instance_label returns label from input' do
|
|
172
|
+
action = create_and_plan_action(
|
|
173
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
174
|
+
@filename,
|
|
175
|
+
@organization.id
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
assert_equal "upload_for_#{@organization.id}", action.send(:instance_label)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
test 'clears previous task output on plan' do
|
|
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
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
test 'rescue_strategy_for_self returns Fail strategy' do
|
|
199
|
+
action = create_and_plan_action(
|
|
200
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
201
|
+
@filename,
|
|
202
|
+
@organization.id
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
assert_equal Dynflow::Action::Rescue::Fail, action.send(:rescue_strategy_for_self)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
test 'handles RestClient server error gracefully' do
|
|
209
|
+
# Create mock response for RestClient exception
|
|
210
|
+
response = mock('response')
|
|
211
|
+
response.stubs(:code).returns(500)
|
|
212
|
+
response.stubs(:body).returns('Server error')
|
|
213
|
+
|
|
214
|
+
# Stub upload_file to raise server error
|
|
215
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
216
|
+
.raises(RestClient::InternalServerError.new(response))
|
|
217
|
+
|
|
218
|
+
action = create_and_plan_action(
|
|
219
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
220
|
+
@filename,
|
|
221
|
+
@organization.id
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# Should raise the error (handled by Dynflow retry mechanism)
|
|
225
|
+
assert_raises(RestClient::InternalServerError) do
|
|
226
|
+
action.send(:try_execute)
|
|
227
|
+
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
|
+
end
|
|
234
|
+
|
|
235
|
+
test 'handles RestClient timeout gracefully' do
|
|
236
|
+
# Stub upload_file to raise timeout (Timeout exception doesn't need response object)
|
|
237
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob.any_instance.stubs(:upload_file)
|
|
238
|
+
.raises(RestClient::Exceptions::Timeout.new)
|
|
239
|
+
|
|
240
|
+
action = create_and_plan_action(
|
|
241
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
242
|
+
@filename,
|
|
243
|
+
@organization.id
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Should raise the error (handled by Dynflow retry mechanism via ExponentialBackoff)
|
|
247
|
+
assert_raises(RestClient::Exceptions::Timeout) do
|
|
248
|
+
action.send(:try_execute)
|
|
249
|
+
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
|
+
end
|
|
256
|
+
|
|
257
|
+
test 'uses proxy configuration from ForemanRhCloud' do
|
|
258
|
+
proxy_url = 'http://proxy.example.com:8080'
|
|
259
|
+
ForemanRhCloud.stubs(:transformed_http_proxy_string).returns(proxy_url)
|
|
260
|
+
|
|
261
|
+
# Create test file
|
|
262
|
+
FileUtils.mkdir_p(File.dirname(@filename))
|
|
263
|
+
FileUtils.touch(@filename)
|
|
264
|
+
|
|
265
|
+
action = create_and_plan_action(
|
|
266
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
267
|
+
@filename,
|
|
268
|
+
@organization.id
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Mock response
|
|
272
|
+
response = mock('response')
|
|
273
|
+
response.stubs(:code).returns(200)
|
|
274
|
+
|
|
275
|
+
# Verify execute_cloud_request is called (which handles proxy)
|
|
276
|
+
# We can't test the actual proxy parameters because CloudRequest concern
|
|
277
|
+
# merges them internally, but we can verify the method is called
|
|
278
|
+
action.expects(:execute_cloud_request).returns(response)
|
|
279
|
+
|
|
280
|
+
# Stub upload_file to call execute_cloud_request (avoiding SSL cert creation issues)
|
|
281
|
+
action.stubs(:upload_file).returns(nil)
|
|
282
|
+
|
|
283
|
+
# Manually call upload_file expectations in the test
|
|
284
|
+
# This simulates what would happen during actual execution
|
|
285
|
+
action.send(:execute_cloud_request,
|
|
286
|
+
method: :post,
|
|
287
|
+
url: ForemanInventoryUpload.upload_url,
|
|
288
|
+
payload: { multipart: true },
|
|
289
|
+
headers: { 'X-Org-Id' => @organization.label })
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
test 'file cleanup when upload aborted due to missing certificate' do
|
|
293
|
+
# Remove certificate from organization
|
|
294
|
+
Organization.any_instance.stubs(:owner_details).returns({})
|
|
295
|
+
|
|
296
|
+
# Create a real test file to verify it's not moved
|
|
297
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
298
|
+
test_file = File.join(@uploads_folder, 'test_file_for_cleanup.tar.xz')
|
|
299
|
+
FileUtils.touch(test_file)
|
|
300
|
+
|
|
301
|
+
begin
|
|
302
|
+
action = create_and_plan_action(
|
|
303
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
304
|
+
test_file,
|
|
305
|
+
@organization.id
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Execute the action
|
|
309
|
+
action.send(:try_execute)
|
|
310
|
+
|
|
311
|
+
# Verify file still exists (not moved or deleted)
|
|
312
|
+
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
|
+
ensure
|
|
323
|
+
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
test 'file cleanup when upload aborted due to disconnected mode' do
|
|
328
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
329
|
+
|
|
330
|
+
# Create a real test file
|
|
331
|
+
FileUtils.mkdir_p(@uploads_folder)
|
|
332
|
+
test_file = File.join(@uploads_folder, 'test_file_disconnected.tar.xz')
|
|
333
|
+
FileUtils.touch(test_file)
|
|
334
|
+
|
|
335
|
+
begin
|
|
336
|
+
action = create_and_plan_action(
|
|
337
|
+
ForemanInventoryUpload::Async::UploadReportDirectJob,
|
|
338
|
+
test_file,
|
|
339
|
+
@organization.id
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Execute the action
|
|
343
|
+
action.send(:try_execute)
|
|
344
|
+
|
|
345
|
+
# Verify file still exists
|
|
346
|
+
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
|
+
ensure
|
|
353
|
+
FileUtils.rm_f(test_file) if File.exist?(test_file)
|
|
354
|
+
end
|
|
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
|
|
@@ -40,7 +40,7 @@ class AccountList extends Component {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const items = Object.keys(filteredAccount).map((label, index) => {
|
|
43
|
-
const account =
|
|
43
|
+
const account = filteredAccount[label];
|
|
44
44
|
return <ListItem key={index} label={label} account={account} />;
|
|
45
45
|
});
|
|
46
46
|
return <Accordion className="account-list">{items}</Accordion>;
|
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
|
+
generate_report_status: 'unknown',
|
|
5
|
+
upload_report_status: 'unknown',
|
|
6
|
+
id: 1,
|
|
7
|
+
report_file_paths: [],
|
|
9
8
|
},
|
|
10
9
|
};
|
|
@@ -10,8 +10,10 @@ import PropTypes from 'prop-types';
|
|
|
10
10
|
import ListItemStatus from '../ListItemStatus';
|
|
11
11
|
import Dashboard from '../../../Dashboard';
|
|
12
12
|
|
|
13
|
-
const ListItem = ({ label, account }) => {
|
|
13
|
+
const ListItem = ({ label, account = {} }) => {
|
|
14
14
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
15
|
+
const accountId = account?.id ?? 0;
|
|
16
|
+
|
|
15
17
|
return (
|
|
16
18
|
<AccordionItem>
|
|
17
19
|
<AccordionToggle
|
|
@@ -30,7 +32,7 @@ const ListItem = ({ label, account }) => {
|
|
|
30
32
|
<ListItemStatus key={`${label}_status`} account={account} />
|
|
31
33
|
</AccordionToggle>
|
|
32
34
|
<AccordionContent isHidden={!isExpanded}>
|
|
33
|
-
<Dashboard accountID={
|
|
35
|
+
<Dashboard accountID={accountId} account={account} />
|
|
34
36
|
</AccordionContent>
|
|
35
37
|
</AccordionItem>
|
|
36
38
|
);
|
|
@@ -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
|
+
"generate_report_status": "unknown",
|
|
22
|
+
"id": 1,
|
|
23
|
+
"report_file_paths": Array [],
|
|
24
|
+
"upload_report_status": "unknown",
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
key="test_status"
|
|
@@ -34,13 +33,13 @@ exports[`ListItem rendering render with Props 1`] = `
|
|
|
34
33
|
<Connect(Dashboard)
|
|
35
34
|
account={
|
|
36
35
|
Object {
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
36
|
+
"generate_report_status": "unknown",
|
|
37
|
+
"id": 1,
|
|
38
|
+
"report_file_paths": Array [],
|
|
39
|
+
"upload_report_status": "unknown",
|
|
42
40
|
}
|
|
43
41
|
}
|
|
42
|
+
accountID={1}
|
|
44
43
|
/>
|
|
45
44
|
</AccordionContent>
|
|
46
45
|
</AccordionItem>
|
|
@@ -49,7 +49,8 @@ class Dashboard extends React.Component {
|
|
|
49
49
|
showFullScreen,
|
|
50
50
|
activeTab,
|
|
51
51
|
} = this.props;
|
|
52
|
-
const downloadButtonDisabled = () =>
|
|
52
|
+
const downloadButtonDisabled = () =>
|
|
53
|
+
!account.report_file_paths || account.report_file_paths.length === 0;
|
|
53
54
|
return (
|
|
54
55
|
<NavContainer
|
|
55
56
|
items={[
|
|
@@ -120,6 +121,7 @@ Dashboard.propTypes = {
|
|
|
120
121
|
generate_report_status: PropTypes.string,
|
|
121
122
|
upload_report_status: PropTypes.string,
|
|
122
123
|
report_file_paths: PropTypes.arrayOf(PropTypes.string),
|
|
124
|
+
id: PropTypes.number,
|
|
123
125
|
}),
|
|
124
126
|
showFullScreen: PropTypes.bool,
|
|
125
127
|
toggleFullScreen: PropTypes.func,
|
|
@@ -140,6 +142,7 @@ Dashboard.defaultProps = {
|
|
|
140
142
|
generate_report_status: 'unknown',
|
|
141
143
|
upload_report_status: 'unknown',
|
|
142
144
|
report_file_paths: [],
|
|
145
|
+
id: 0,
|
|
143
146
|
},
|
|
144
147
|
showFullScreen: false,
|
|
145
148
|
toggleFullScreen: noop,
|
|
@@ -6,26 +6,33 @@ import InventoryFilter from '../InventoryFilter';
|
|
|
6
6
|
import ToolbarButtons from './components/ToolbarButtons';
|
|
7
7
|
import SettingsWarning from './components/SettingsWarning';
|
|
8
8
|
import PageTitle from './PageTitle';
|
|
9
|
+
import { useIopConfig } from '../../../common/Hooks/ConfigHooks';
|
|
9
10
|
import './PageHeader.scss';
|
|
10
11
|
|
|
11
|
-
const PageHeader = () =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<div className="inventory-upload-header
|
|
16
|
-
<
|
|
17
|
-
<
|
|
12
|
+
const PageHeader = () => {
|
|
13
|
+
const isIop = useIopConfig();
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="inventory-upload-header">
|
|
17
|
+
<SettingsWarning />
|
|
18
|
+
<PageTitle />
|
|
19
|
+
{!isIop && (
|
|
20
|
+
<div className="inventory-upload-header-description">
|
|
21
|
+
<InventorySettings />
|
|
22
|
+
<PageDescription />
|
|
23
|
+
</div>
|
|
24
|
+
)}
|
|
25
|
+
<Grid.Row>
|
|
26
|
+
<Grid.Col xs={4}>
|
|
27
|
+
<InventoryFilter />
|
|
28
|
+
</Grid.Col>
|
|
29
|
+
<Grid.Col xs={7} xsOffset={1}>
|
|
30
|
+
<ToolbarButtons />
|
|
31
|
+
</Grid.Col>
|
|
32
|
+
</Grid.Row>
|
|
18
33
|
</div>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<InventoryFilter />
|
|
22
|
-
</Grid.Col>
|
|
23
|
-
<Grid.Col xs={7} xsOffset={1}>
|
|
24
|
-
<ToolbarButtons />
|
|
25
|
-
</Grid.Col>
|
|
26
|
-
</Grid.Row>
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
34
|
+
);
|
|
35
|
+
};
|
|
29
36
|
|
|
30
37
|
PageHeader.propTypes = {};
|
|
31
38
|
|