foreman_rh_cloud 12.0.0 → 12.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -4
- data/app/controllers/concerns/inventory_upload/report_actions.rb +1 -1
- data/app/controllers/foreman_inventory_upload/accounts_controller.rb +2 -0
- data/app/controllers/foreman_inventory_upload/uploads_settings_controller.rb +2 -0
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +26 -22
- data/app/services/foreman_rh_cloud/cloud_request.rb +13 -3
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +17 -3
- data/app/services/foreman_rh_cloud/rules_ingester.rb +12 -1
- data/config/routes.rb +4 -0
- data/lib/foreman_inventory_upload/generators/queries.rb +2 -0
- data/lib/foreman_inventory_upload/generators/slice.rb +83 -42
- data/lib/foreman_inventory_upload.rb +5 -0
- data/lib/foreman_rh_cloud/engine.rb +15 -3
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/foreman_rh_cloud.rb +2 -0
- data/package.json +1 -1
- data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +35 -2
- data/test/unit/slice_generator_test.rb +212 -4
- data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +5 -1
- data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/Dashboard.test.js.snap +2 -1
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/AdvancedSettingsConstants.js +27 -8
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/index.js +11 -3
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.js +71 -10
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettingsSelectors.js +13 -1
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/MinimalInventoryDropdown.js +107 -0
- data/webpack/ForemanInventoryUpload/Components/NavContainer/NavContainer.fixtures.js +9 -2
- data/webpack/ForemanInventoryUpload/Components/NavContainer/NavContainer.js +8 -0
- data/webpack/ForemanInventoryUpload/Components/NavContainer/__tests__/NavContainer.test.js +53 -9
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +72 -58
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/PageDescription.test.js +61 -6
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +18 -6
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +54 -6
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.fixtures.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.js +8 -0
- data/webpack/ForemanInventoryUpload/Components/ReportGenerate/__tests__/__snapshots__/ReportGenerate.test.js.snap +4 -2
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUpload.js +1 -8
- data/webpack/ForemanInventoryUpload/Components/ReportUpload/__tests__/__snapshots__/ReportUpload.test.js.snap +4 -2
- data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +47 -28
- data/webpack/ForemanInventoryUpload/Components/TabHeader/__tests__/TabHeader.test.js +46 -8
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +2 -7
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +1 -6
- data/webpack/common/Switcher/SwitcherPF4.js +11 -1
- metadata +4 -11
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/InventorySettings.test.js +0 -13
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/__snapshots__/InventorySettings.test.js.snap +0 -31
- data/webpack/ForemanInventoryUpload/Components/NavContainer/__tests__/__snapshots__/NavContainer.test.js.snap +0 -89
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +0 -62
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/__snapshots__/ToolbarButtons.test.js.snap +0 -10
- data/webpack/ForemanInventoryUpload/Components/TabHeader/__tests__/__snapshots__/TabHeader.test.js.snap +0 -43
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/components/AdvancedSettings/AdvancedSettings.js +0 -72
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/components/AdvancedSettings/index.js +0 -23
@@ -35,6 +35,12 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
35
35
|
ForemanInventoryUpload::Generators::Queries.instance_variable_set(:@fact_names, nil)
|
36
36
|
end
|
37
37
|
|
38
|
+
def create_fact_values(host, facts)
|
39
|
+
facts.each do |fact_name, value|
|
40
|
+
FactoryBot.create(:fact_value, fact_name: fact_names[fact_name], value: value, host: host)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
38
44
|
def interesting_facts
|
39
45
|
[
|
40
46
|
'dmi::system::uuid',
|
@@ -52,6 +58,8 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
52
58
|
'distribution::version',
|
53
59
|
'distribution::id',
|
54
60
|
'virt::is_guest',
|
61
|
+
'hypervisor::type',
|
62
|
+
'hypervisor::version',
|
55
63
|
'dmi::system::manufacturer',
|
56
64
|
'dmi::system::product_name',
|
57
65
|
'dmi::chassis::asset_tag',
|
@@ -98,10 +106,210 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
98
106
|
assert_equal 'test_nic1', actual_nic['name']
|
99
107
|
end
|
100
108
|
|
109
|
+
test 'generates a report with minimal data collection' do
|
110
|
+
Setting[:insights_minimal_data_collection] = true
|
111
|
+
create_fact_values(@host,
|
112
|
+
'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7',
|
113
|
+
'dmi::bios::vendor' => 'SeaBios',
|
114
|
+
'dmi::bios::version' => '10',
|
115
|
+
'cpu::cpu_socket(s)' => '2',
|
116
|
+
'cpu::cpu(s)' => '4',
|
117
|
+
'cpu::core(s)_per_socket' => '1',
|
118
|
+
'memory::memtotal' => '1024',
|
119
|
+
'insights_id' => '00000000-0073-0400-0000-000000000000')
|
120
|
+
|
121
|
+
batch = Host.where(id: @host.id).in_batches.first
|
122
|
+
generator = create_generator(batch)
|
123
|
+
|
124
|
+
json_str = generator.render
|
125
|
+
actual = JSON.parse(json_str.join("\n"))
|
126
|
+
|
127
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
128
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
129
|
+
assert_equal 1, generator.hosts_count
|
130
|
+
assert_equal '1234', actual_host['account']
|
131
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
132
|
+
assert_not_nil actual_host['subscription_manager_id']
|
133
|
+
assert_equal 'D30B0B42-7824-2635-C62D-491394DE43F7', actual_host['bios_uuid']
|
134
|
+
assert_equal '00000000-0073-0400-0000-000000000000', actual_host['insights_id']
|
135
|
+
assert_equal 4, actual_system_profile['number_of_cpus']
|
136
|
+
assert_equal 2, actual_system_profile['number_of_sockets']
|
137
|
+
assert_equal 1_048_576, actual_system_profile['system_memory_bytes']
|
138
|
+
assert_equal 1, actual_system_profile['cores_per_socket']
|
139
|
+
assert_equal 'SeaBios', actual_host['bios_vendor']
|
140
|
+
assert_equal '10', actual_host['bios_version']
|
141
|
+
assert_equal '2', actual_host['cpu_socket(s)']
|
142
|
+
# Assert exclusion of non-minimal data collection fact
|
143
|
+
assert_nil actual_host['ip_addresses']
|
144
|
+
assert_nil actual_host['mac_addresses']
|
145
|
+
assert_nil actual_host['fqdn']
|
146
|
+
end
|
147
|
+
|
148
|
+
test 'generates a report with minimal data collection for a hypervisor' do
|
149
|
+
Setting[:insights_minimal_data_collection] = true
|
150
|
+
create_fact_values(@host,
|
151
|
+
'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7',
|
152
|
+
'hypervisor::type' => 'VMware',
|
153
|
+
'hypervisor::version' => '6.7',
|
154
|
+
'cpu::cpu_socket(s)' => '2',
|
155
|
+
'cpu::cpu(s)' => '4',
|
156
|
+
'cpu::core(s)_per_socket' => '1',
|
157
|
+
'memory::memtotal' => '1024')
|
158
|
+
|
159
|
+
@host.subscription_facet.hypervisor = true
|
160
|
+
@host.subscription_facet.save!
|
161
|
+
|
162
|
+
batch = Host.where(id: @host.id).in_batches.first
|
163
|
+
generator = create_generator(batch)
|
164
|
+
|
165
|
+
json_str = generator.render
|
166
|
+
actual = JSON.parse(json_str.join("\n"))
|
167
|
+
|
168
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
169
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
170
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
171
|
+
assert_equal 'D30B0B42-7824-2635-C62D-491394DE43F7', actual_host['bios_uuid']
|
172
|
+
assert_equal 'VMware', actual_host['hypervisor_type']
|
173
|
+
assert_equal '6.7', actual_host['hypervisor_version']
|
174
|
+
assert_equal '2', actual_host['cpu_socket(s)']
|
175
|
+
assert_equal 4, actual_system_profile['number_of_cpus']
|
176
|
+
assert_equal 2, actual_system_profile['number_of_sockets']
|
177
|
+
assert_equal 1_048_576, actual_system_profile['system_memory_bytes']
|
178
|
+
assert_equal 1, actual_system_profile['cores_per_socket']
|
179
|
+
assert_equal 1, generator.hosts_count
|
180
|
+
# Assert exclusion of non-minimal data collection facts
|
181
|
+
assert_nil actual_host['ip_addresses']
|
182
|
+
assert_nil actual_host['mac_addresses']
|
183
|
+
assert_nil actual_host['fqdn']
|
184
|
+
assert true, @host.subscription_facet.hypervisor?
|
185
|
+
end
|
186
|
+
|
187
|
+
test 'packages are excluded in the report with minimal data collection' do
|
188
|
+
Setting[:exclude_installed_packages] = false
|
189
|
+
Setting[:insights_minimal_data_collection] = true
|
190
|
+
|
191
|
+
installed_package = ::Katello::InstalledPackage.create(name: 'test-package', nvrea: 'test-package-1.0.x86_64', nvra: 'test-package-1.0.x86_64')
|
192
|
+
another_host = FactoryBot.create(
|
193
|
+
:host,
|
194
|
+
:with_subscription,
|
195
|
+
:with_content,
|
196
|
+
content_view: @host.content_views.first,
|
197
|
+
lifecycle_environment: @host.lifecycle_environments.first,
|
198
|
+
organization: @host.organization,
|
199
|
+
installed_packages: [installed_package]
|
200
|
+
)
|
201
|
+
create_fact_values(another_host,
|
202
|
+
'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7',
|
203
|
+
'dmi::bios::vendor' => 'SeaBios',
|
204
|
+
'dmi::bios::version' => '10',
|
205
|
+
'cpu::cpu_socket(s)' => '2',
|
206
|
+
'cpu::cpu(s)' => '4',
|
207
|
+
'cpu::core(s)_per_socket' => '1',
|
208
|
+
'memory::memtotal' => '1024')
|
209
|
+
|
210
|
+
batch = Host.where(id: another_host.id).in_batches.first
|
211
|
+
generator = create_generator(batch)
|
212
|
+
|
213
|
+
json_str = generator.render
|
214
|
+
actual = JSON.parse(json_str.join("\n"))
|
215
|
+
|
216
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
217
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
218
|
+
assert_not_nil(actual_host['system_profile'])
|
219
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
220
|
+
assert_not_nil actual_host['subscription_manager_id']
|
221
|
+
assert_equal 'D30B0B42-7824-2635-C62D-491394DE43F7', actual_host['bios_uuid']
|
222
|
+
assert_equal 4, actual_system_profile['number_of_cpus']
|
223
|
+
assert_equal 2, actual_system_profile['number_of_sockets']
|
224
|
+
assert_equal 1_048_576, actual_system_profile['system_memory_bytes']
|
225
|
+
assert_equal 1, actual_system_profile['cores_per_socket']
|
226
|
+
assert_equal 'SeaBios', actual_host['bios_vendor']
|
227
|
+
assert_equal '10', actual_host['bios_version']
|
228
|
+
assert_equal '2', actual_host['cpu_socket(s)']
|
229
|
+
assert_nil actual_host['installed_packages']
|
230
|
+
end
|
231
|
+
|
232
|
+
test 'generates a report with minimal data collection with ip setting overridden' do
|
233
|
+
Setting[:insights_minimal_data_collection] = true
|
234
|
+
Setting[:obfuscate_inventory_ips] = false
|
235
|
+
create_fact_values(@host,
|
236
|
+
'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7',
|
237
|
+
'dmi::bios::vendor' => 'SeaBios',
|
238
|
+
'dmi::bios::version' => '10',
|
239
|
+
'cpu::cpu_socket(s)' => '2',
|
240
|
+
'cpu::cpu(s)' => '4',
|
241
|
+
'cpu::core(s)_per_socket' => '1',
|
242
|
+
'memory::memtotal' => '1024')
|
243
|
+
|
244
|
+
batch = Host.where(id: @host.id).in_batches.first
|
245
|
+
generator = create_generator(batch)
|
246
|
+
|
247
|
+
json_str = generator.render
|
248
|
+
actual = JSON.parse(json_str.join("\n"))
|
249
|
+
|
250
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
251
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
252
|
+
assert_equal 1, generator.hosts_count
|
253
|
+
assert_not_nil(actual_host['system_profile'])
|
254
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
255
|
+
assert_not_nil actual_host['subscription_manager_id']
|
256
|
+
assert_equal 'D30B0B42-7824-2635-C62D-491394DE43F7', actual_host['bios_uuid']
|
257
|
+
assert_equal 4, actual_system_profile['number_of_cpus']
|
258
|
+
assert_equal 2, actual_system_profile['number_of_sockets']
|
259
|
+
assert_equal 1_048_576, actual_system_profile['system_memory_bytes']
|
260
|
+
assert_equal 1, actual_system_profile['cores_per_socket']
|
261
|
+
assert_equal 'SeaBios', actual_host['bios_vendor']
|
262
|
+
assert_equal '10', actual_host['bios_version']
|
263
|
+
assert_equal '2', actual_host['cpu_socket(s)']
|
264
|
+
# Assert exclusion of non-minimal data collection fact
|
265
|
+
assert_nil actual_host['ip_addresses']
|
266
|
+
assert_nil actual_host['mac_addresses']
|
267
|
+
assert_nil actual_host['fqdn']
|
268
|
+
end
|
269
|
+
|
270
|
+
test 'generates a report with minimal data collection with fqdn setting overridden' do
|
271
|
+
Setting[:insights_minimal_data_collection] = true
|
272
|
+
Setting[:obfuscate_inventory_hostnames] = false
|
273
|
+
create_fact_values(@host,
|
274
|
+
'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7',
|
275
|
+
'dmi::bios::vendor' => 'SeaBios',
|
276
|
+
'dmi::bios::version' => '10',
|
277
|
+
'cpu::cpu_socket(s)' => '2',
|
278
|
+
'cpu::cpu(s)' => '4',
|
279
|
+
'cpu::core(s)_per_socket' => '1',
|
280
|
+
'memory::memtotal' => '1024')
|
281
|
+
|
282
|
+
batch = Host.where(id: @host.id).in_batches.first
|
283
|
+
generator = create_generator(batch)
|
284
|
+
|
285
|
+
json_str = generator.render
|
286
|
+
actual = JSON.parse(json_str.join("\n"))
|
287
|
+
|
288
|
+
assert_equal '00000000-0000-0000-0000-000000000000', actual['report_slice_id']
|
289
|
+
assert_not_nil(actual_host = actual['hosts'].first)
|
290
|
+
assert_not_nil(actual_host['system_profile'])
|
291
|
+
assert_not_nil(actual_system_profile = actual_host['system_profile'])
|
292
|
+
assert_not_nil actual_host['subscription_manager_id']
|
293
|
+
assert_equal 'D30B0B42-7824-2635-C62D-491394DE43F7', actual_host['bios_uuid']
|
294
|
+
assert_equal 4, actual_system_profile['number_of_cpus']
|
295
|
+
assert_equal 2, actual_system_profile['number_of_sockets']
|
296
|
+
assert_equal 1_048_576, actual_system_profile['system_memory_bytes']
|
297
|
+
assert_equal 1, actual_system_profile['cores_per_socket']
|
298
|
+
assert_equal 'SeaBios', actual_host['bios_vendor']
|
299
|
+
assert_equal '10', actual_host['bios_version']
|
300
|
+
assert_equal '2', actual_host['cpu_socket(s)']
|
301
|
+
# Assert exclusion of non-minimal data collection fact
|
302
|
+
assert_nil actual_host['ip_addresses']
|
303
|
+
assert_nil actual_host['mac_addresses']
|
304
|
+
assert_nil actual_host['fqdn']
|
305
|
+
assert_equal 1, generator.hosts_count
|
306
|
+
end
|
307
|
+
|
101
308
|
test 'hosts report fields should be present if fact exist' do
|
102
|
-
|
103
|
-
|
104
|
-
|
309
|
+
create_fact_values(@host,
|
310
|
+
'cpu::cpu(s)' => '4',
|
311
|
+
'cpu::cpu_socket(s)' => '2',
|
312
|
+
'cpu::core(s)_per_socket' => '1')
|
105
313
|
|
106
314
|
batch = Host.where(id: @host.id).in_batches.first
|
107
315
|
generator = create_generator(batch)
|
@@ -704,7 +912,7 @@ class SliceGeneratorTest < ActiveSupport::TestCase
|
|
704
912
|
end
|
705
913
|
|
706
914
|
test 'passes valid bios_uuid field' do
|
707
|
-
|
915
|
+
create_fact_values(@host, 'dmi::system::uuid' => 'D30B0B42-7824-2635-C62D-491394DE43F7')
|
708
916
|
|
709
917
|
batch = Host.where(id: @host.id).in_batches.first
|
710
918
|
generator = create_generator(batch)
|
@@ -49,6 +49,7 @@ class Dashboard extends React.Component {
|
|
49
49
|
showFullScreen,
|
50
50
|
activeTab,
|
51
51
|
} = this.props;
|
52
|
+
const downloadButtonDisabled = () => account.report_file_paths.length === 0;
|
52
53
|
return (
|
53
54
|
<NavContainer
|
54
55
|
items={[
|
@@ -60,6 +61,8 @@ class Dashboard extends React.Component {
|
|
60
61
|
...generating,
|
61
62
|
restartProcess: this.handleRestart,
|
62
63
|
exitCode: account.generate_report_status,
|
64
|
+
downloadReports: this.handleDownload,
|
65
|
+
downloadButtonDisabled,
|
63
66
|
toggleFullScreen: this.handleToggleFullScreen,
|
64
67
|
},
|
65
68
|
onClick: () => this.handleTabChange('generating'),
|
@@ -70,7 +73,6 @@ class Dashboard extends React.Component {
|
|
70
73
|
component: ReportUpload,
|
71
74
|
props: {
|
72
75
|
...uploading,
|
73
|
-
downloadReports: this.handleDownload,
|
74
76
|
exitCode: account.upload_report_status,
|
75
77
|
toggleFullScreen: this.handleToggleFullScreen,
|
76
78
|
},
|
@@ -117,6 +119,7 @@ Dashboard.propTypes = {
|
|
117
119
|
account: PropTypes.shape({
|
118
120
|
generate_report_status: PropTypes.string,
|
119
121
|
upload_report_status: PropTypes.string,
|
122
|
+
report_file_paths: PropTypes.arrayOf(PropTypes.string),
|
120
123
|
}),
|
121
124
|
showFullScreen: PropTypes.bool,
|
122
125
|
toggleFullScreen: PropTypes.func,
|
@@ -136,6 +139,7 @@ Dashboard.defaultProps = {
|
|
136
139
|
account: {
|
137
140
|
generate_report_status: 'unknown',
|
138
141
|
upload_report_status: 'unknown',
|
142
|
+
report_file_paths: [],
|
139
143
|
},
|
140
144
|
showFullScreen: false,
|
141
145
|
toggleFullScreen: noop,
|
@@ -10,6 +10,8 @@ exports[`Dashboard rendering with props 1`] = `
|
|
10
10
|
"name": "Generating",
|
11
11
|
"onClick": [Function],
|
12
12
|
"props": Object {
|
13
|
+
"downloadButtonDisabled": [Function],
|
14
|
+
"downloadReports": [Function],
|
13
15
|
"exitCode": "unknown",
|
14
16
|
"restartProcess": [Function],
|
15
17
|
"toggleFullScreen": [Function],
|
@@ -21,7 +23,6 @@ exports[`Dashboard rendering with props 1`] = `
|
|
21
23
|
"name": "Uploading",
|
22
24
|
"onClick": [Function],
|
23
25
|
"props": Object {
|
24
|
-
"downloadReports": [Function],
|
25
26
|
"exitCode": "unknown",
|
26
27
|
"toggleFullScreen": [Function],
|
27
28
|
},
|
@@ -8,6 +8,27 @@ export const settingsDict = {
|
|
8
8
|
'Enable automatic upload of your hosts inventory to the Red Hat cloud'
|
9
9
|
),
|
10
10
|
},
|
11
|
+
allowAutoInsightsMismatchDelete: {
|
12
|
+
name: 'allow_auto_insights_mismatch_delete',
|
13
|
+
label: __('Automatic mismatch deletion'),
|
14
|
+
tooltip: __(
|
15
|
+
'Enable automatic deletion of mismatched host records from the Red Hat cloud'
|
16
|
+
),
|
17
|
+
},
|
18
|
+
};
|
19
|
+
|
20
|
+
// we don't use this anywhere, but leaving the comment just so you can, like, see
|
21
|
+
// export const parentSettingsDict = {
|
22
|
+
// insightsMinimalDataCollection: {
|
23
|
+
// name: 'insights_minimal_data_collection',
|
24
|
+
// label: __('Minimal data collection'),
|
25
|
+
// tooltip: __(
|
26
|
+
// 'Only send the minimum required data to Red Hat cloud, and obfuscate wherever possible'
|
27
|
+
// ),
|
28
|
+
// },
|
29
|
+
// };
|
30
|
+
|
31
|
+
export const childSettingsDict = {
|
11
32
|
hostObfuscationEnabled: {
|
12
33
|
name: 'obfuscate_inventory_hostnames',
|
13
34
|
label: __('Obfuscate host names'),
|
@@ -20,16 +41,14 @@ export const settingsDict = {
|
|
20
41
|
},
|
21
42
|
excludePackagesEnabled: {
|
22
43
|
name: 'exclude_installed_packages',
|
23
|
-
label: __('Exclude installed
|
44
|
+
label: __('Exclude installed packages'),
|
24
45
|
tooltip: __(
|
25
46
|
'Exclude installed packages from being uploaded to the Red Hat cloud'
|
26
47
|
),
|
27
48
|
},
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
),
|
34
|
-
},
|
49
|
+
};
|
50
|
+
|
51
|
+
export const allSettingsDict = {
|
52
|
+
...settingsDict,
|
53
|
+
...childSettingsDict,
|
35
54
|
};
|
@@ -4,9 +4,8 @@ import { useSelector, useDispatch } from 'react-redux';
|
|
4
4
|
import { selectSettings } from '../InventorySettingsSelectors';
|
5
5
|
import { handleToggle } from './AdvancedSettingActions';
|
6
6
|
import SwitcherPF4 from '../../../../common/Switcher/SwitcherPF4';
|
7
|
-
import { settingsDict } from './AdvancedSettingsConstants';
|
8
7
|
|
9
|
-
const AdvancedSetting = ({ setting }) => {
|
8
|
+
const AdvancedSetting = ({ setting, settingsDict, isLocked, lockedValue }) => {
|
10
9
|
const settingValue = useSelector(store => selectSettings(store)[setting]);
|
11
10
|
const dispatch = useDispatch();
|
12
11
|
const onToggle = () =>
|
@@ -16,7 +15,8 @@ const AdvancedSetting = ({ setting }) => {
|
|
16
15
|
id={settingsDict[setting].name}
|
17
16
|
label={settingsDict[setting].label}
|
18
17
|
tooltip={settingsDict[setting].tooltip}
|
19
|
-
isChecked={settingValue}
|
18
|
+
isChecked={isLocked ? lockedValue : settingValue}
|
19
|
+
isDisabled={isLocked}
|
20
20
|
onChange={onToggle}
|
21
21
|
/>
|
22
22
|
);
|
@@ -24,6 +24,14 @@ const AdvancedSetting = ({ setting }) => {
|
|
24
24
|
|
25
25
|
AdvancedSetting.propTypes = {
|
26
26
|
setting: PropTypes.string.isRequired,
|
27
|
+
settingsDict: PropTypes.shape({}).isRequired,
|
28
|
+
isLocked: PropTypes.bool,
|
29
|
+
lockedValue: PropTypes.bool,
|
30
|
+
};
|
31
|
+
|
32
|
+
AdvancedSetting.defaultProps = {
|
33
|
+
isLocked: false,
|
34
|
+
lockedValue: true,
|
27
35
|
};
|
28
36
|
|
29
37
|
export default AdvancedSetting;
|
@@ -1,18 +1,79 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import { useSelector } from 'react-redux';
|
2
3
|
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
import { Flex, FlexItem } from '@patternfly/react-core';
|
3
5
|
|
4
6
|
import AdvancedSetting from './AdvancedSetting';
|
5
|
-
import {
|
7
|
+
import {
|
8
|
+
childSettingsDict,
|
9
|
+
settingsDict,
|
10
|
+
} from './AdvancedSetting/AdvancedSettingsConstants';
|
11
|
+
import {
|
12
|
+
selectSubscriptionConnectionEnabled,
|
13
|
+
selectInsightsMinimalDataCollection,
|
14
|
+
} from './InventorySettingsSelectors'; // Make sure this path is correct!
|
15
|
+
import MinimalInventoryDropdown from './MinimalInventoryDropdown';
|
6
16
|
|
7
17
|
import './InventorySettings.scss';
|
8
18
|
|
9
|
-
const InventorySettings = () =>
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
))
|
15
|
-
|
16
|
-
);
|
19
|
+
const InventorySettings = () => {
|
20
|
+
const subscriptionConnectionEnabled = useSelector(
|
21
|
+
state => selectSubscriptionConnectionEnabled(state) // Added (state) =>
|
22
|
+
);
|
23
|
+
const insightsMinimalDataCollection = useSelector(
|
24
|
+
state => selectInsightsMinimalDataCollection(state) // Added (state) =>
|
25
|
+
);
|
26
|
+
const [chosenValue, setChosenValue] = useState(null);
|
27
|
+
const settingKeys = new Set(Object.keys(settingsDict));
|
28
|
+
|
29
|
+
if (!subscriptionConnectionEnabled) {
|
30
|
+
settingKeys.delete('autoUploadEnabled');
|
31
|
+
}
|
32
|
+
|
33
|
+
return (
|
34
|
+
<div className="inventory-settings">
|
35
|
+
<h3>{__('Settings')}</h3>
|
36
|
+
{[...settingKeys].map(key => {
|
37
|
+
const isChildSetting = Object.hasOwnProperty.call(
|
38
|
+
childSettingsDict,
|
39
|
+
key
|
40
|
+
);
|
41
|
+
return (
|
42
|
+
<AdvancedSetting
|
43
|
+
key={key}
|
44
|
+
setting={key}
|
45
|
+
settingsDict={isChildSetting ? childSettingsDict : settingsDict}
|
46
|
+
isLocked={
|
47
|
+
isChildSetting &&
|
48
|
+
(chosenValue === 'minimal' || insightsMinimalDataCollection)
|
49
|
+
}
|
50
|
+
/>
|
51
|
+
);
|
52
|
+
})}
|
53
|
+
<MinimalInventoryDropdown setChosenValue={setChosenValue} />
|
54
|
+
{Object.keys(childSettingsDict).length > 0 && ( // Only render this section if there are child settings
|
55
|
+
<div style={{ marginTop: '1.5em' }}>
|
56
|
+
<Flex>
|
57
|
+
<FlexItem>
|
58
|
+
<span style={{ width: '6em' }} />
|
59
|
+
</FlexItem>
|
60
|
+
<FlexItem>
|
61
|
+
{Object.keys(childSettingsDict).map(key => (
|
62
|
+
<AdvancedSetting
|
63
|
+
key={key}
|
64
|
+
setting={key}
|
65
|
+
settingsDict={childSettingsDict}
|
66
|
+
isLocked={
|
67
|
+
chosenValue === 'minimal' || insightsMinimalDataCollection
|
68
|
+
}
|
69
|
+
/>
|
70
|
+
))}
|
71
|
+
</FlexItem>
|
72
|
+
</Flex>
|
73
|
+
</div>
|
74
|
+
)}
|
75
|
+
</div>
|
76
|
+
);
|
77
|
+
};
|
17
78
|
|
18
79
|
export default InventorySettings;
|
data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettingsSelectors.js
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
selectAPIResponse,
|
3
|
+
selectAPIStatus,
|
4
|
+
} from 'foremanReact/redux/API/APISelectors';
|
2
5
|
import { INVENTORY_SETTINGS } from './InventorySettingsConstants';
|
3
6
|
|
4
7
|
export const selectSettings = state =>
|
5
8
|
selectAPIResponse(state, INVENTORY_SETTINGS);
|
6
9
|
|
10
|
+
export const selectSettingsStatus = state =>
|
11
|
+
selectAPIStatus(state, INVENTORY_SETTINGS);
|
12
|
+
|
7
13
|
export const selectAutoUploadEnabled = state =>
|
8
14
|
selectSettings(state).autoUploadEnabled;
|
9
15
|
|
16
|
+
export const selectSubscriptionConnectionEnabled = state =>
|
17
|
+
selectSettings(state).subscriptionConnectionEnabled;
|
18
|
+
|
10
19
|
export const selectHostObfuscationEnabled = state =>
|
11
20
|
selectSettings(state).hostObfuscationEnabled;
|
12
21
|
|
@@ -18,3 +27,6 @@ export const selectExcludePackages = state =>
|
|
18
27
|
|
19
28
|
export const selectMismatchDelete = state =>
|
20
29
|
selectSettings(state).allowAutoInsightsMismatchDelete;
|
30
|
+
|
31
|
+
export const selectInsightsMinimalDataCollection = state =>
|
32
|
+
selectSettings(state).insightsMinimalDataCollection;
|
@@ -0,0 +1,107 @@
|
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { useDispatch, useSelector } from 'react-redux';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
5
|
+
import {
|
6
|
+
Dropdown,
|
7
|
+
DropdownItem,
|
8
|
+
DropdownList,
|
9
|
+
MenuToggle,
|
10
|
+
} from '@patternfly/react-core';
|
11
|
+
|
12
|
+
import { childSettingsDict } from './AdvancedSetting/AdvancedSettingsConstants';
|
13
|
+
import { setSetting } from './InventorySettingsActions';
|
14
|
+
|
15
|
+
import { selectInsightsMinimalDataCollection } from './InventorySettingsSelectors';
|
16
|
+
|
17
|
+
const MinimalInventoryDropdown = ({ setChosenValue }) => {
|
18
|
+
const dispatch = useDispatch();
|
19
|
+
const [isOpen, setIsOpen] = useState(false);
|
20
|
+
const dropdownValues = {
|
21
|
+
minimal: {
|
22
|
+
title: __('Minimal data collection'),
|
23
|
+
description: __(
|
24
|
+
'Only send the minimum required data to Red Hat cloud, obfuscation settings are disabled'
|
25
|
+
),
|
26
|
+
},
|
27
|
+
optional: {
|
28
|
+
title: __('Optional data collection'),
|
29
|
+
description: __(
|
30
|
+
'Send additional data to enhance Insights services, as per the settings'
|
31
|
+
),
|
32
|
+
},
|
33
|
+
};
|
34
|
+
const valueToBoolean = {
|
35
|
+
minimal: true,
|
36
|
+
optional: false,
|
37
|
+
};
|
38
|
+
const currentSettingBoolean = useSelector(
|
39
|
+
selectInsightsMinimalDataCollection
|
40
|
+
);
|
41
|
+
const currentDropdownValue = currentSettingBoolean ? 'minimal' : 'optional';
|
42
|
+
const onToggleClick = () => {
|
43
|
+
setIsOpen(!isOpen);
|
44
|
+
};
|
45
|
+
const onSelect = (_event, value) => {
|
46
|
+
setIsOpen(false);
|
47
|
+
setChosenValue(value);
|
48
|
+
|
49
|
+
dispatch(
|
50
|
+
setSetting({
|
51
|
+
setting: 'insights_minimal_data_collection',
|
52
|
+
value: valueToBoolean[value],
|
53
|
+
})
|
54
|
+
);
|
55
|
+
|
56
|
+
if (value === 'minimal') {
|
57
|
+
// If user wants to move to minimal data collection, turn on all related settings.
|
58
|
+
// These will be overridden by insights_minimal_data_collection anyway, but this takes care of the visuals.
|
59
|
+
Object.values(childSettingsDict).forEach(setting => {
|
60
|
+
dispatch(
|
61
|
+
setSetting({
|
62
|
+
setting: setting.name,
|
63
|
+
value: true,
|
64
|
+
})
|
65
|
+
);
|
66
|
+
});
|
67
|
+
}
|
68
|
+
};
|
69
|
+
return (
|
70
|
+
<Dropdown
|
71
|
+
isOpen={isOpen}
|
72
|
+
onSelect={onSelect}
|
73
|
+
onOpenChange={val => setIsOpen(val)}
|
74
|
+
toggle={toggleRef => (
|
75
|
+
<MenuToggle
|
76
|
+
ref={toggleRef}
|
77
|
+
isFullWidth
|
78
|
+
onClick={onToggleClick}
|
79
|
+
isExpanded={isOpen}
|
80
|
+
>
|
81
|
+
{dropdownValues[currentDropdownValue].title}
|
82
|
+
</MenuToggle>
|
83
|
+
)}
|
84
|
+
shouldFocusToggleOnSelect
|
85
|
+
>
|
86
|
+
<div style={{ maxWidth: '28em' }}>
|
87
|
+
<DropdownList>
|
88
|
+
{Object.entries(dropdownValues).map(([value, item]) => (
|
89
|
+
<DropdownItem
|
90
|
+
value={value}
|
91
|
+
key={value}
|
92
|
+
description={item.description}
|
93
|
+
>
|
94
|
+
{item.title}
|
95
|
+
</DropdownItem>
|
96
|
+
))}
|
97
|
+
</DropdownList>
|
98
|
+
</div>
|
99
|
+
</Dropdown>
|
100
|
+
);
|
101
|
+
};
|
102
|
+
|
103
|
+
MinimalInventoryDropdown.propTypes = {
|
104
|
+
setChosenValue: PropTypes.func.isRequired,
|
105
|
+
};
|
106
|
+
|
107
|
+
export default MinimalInventoryDropdown;
|
@@ -1,12 +1,19 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { noop } from 'foremanReact/common/helpers';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
3
4
|
|
4
5
|
export const props = {
|
5
6
|
items: [
|
6
7
|
{
|
7
8
|
icon: 'some-icon',
|
8
|
-
name: '
|
9
|
-
component: () => <p>
|
9
|
+
name: __('Generating'),
|
10
|
+
component: () => <p>test1</p>,
|
11
|
+
onClick: noop,
|
12
|
+
},
|
13
|
+
{
|
14
|
+
icon: 'other-icon',
|
15
|
+
name: __('Uploading'),
|
16
|
+
component: () => <p>test2</p>,
|
10
17
|
onClick: noop,
|
11
18
|
},
|
12
19
|
],
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { useSelector } from 'react-redux';
|
2
3
|
import PropTypes from 'prop-types';
|
3
4
|
import {
|
4
5
|
TabContainer,
|
@@ -9,8 +10,10 @@ import {
|
|
9
10
|
Icon,
|
10
11
|
noop,
|
11
12
|
} from 'patternfly-react';
|
13
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
12
14
|
import './navContainer.scss';
|
13
15
|
import FullScreenModal from '../FullScreenModal';
|
16
|
+
import { selectSubscriptionConnectionEnabled } from '../InventorySettings/InventorySettingsSelectors';
|
14
17
|
|
15
18
|
const NavContainer = ({
|
16
19
|
items,
|
@@ -18,8 +21,13 @@ const NavContainer = ({
|
|
18
21
|
toggleFullScreen,
|
19
22
|
terminalProps,
|
20
23
|
}) => {
|
24
|
+
const subscriptionConnectionEnabled = useSelector(
|
25
|
+
selectSubscriptionConnectionEnabled
|
26
|
+
);
|
21
27
|
const navItems = items.map((item, index) => {
|
22
28
|
const { name, icon, onClick } = item;
|
29
|
+
if (name === __('Uploading') && !subscriptionConnectionEnabled) return null;
|
30
|
+
|
23
31
|
return (
|
24
32
|
<NavItem
|
25
33
|
key={index}
|