foreman_rh_cloud 2.0.4 → 2.0.5

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_inventory_upload/accounts_controller.rb +1 -0
  3. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +14 -7
  4. data/app/models/setting/rh_cloud.rb +13 -0
  5. data/config/routes.rb +1 -0
  6. data/lib/foreman_inventory_upload.rb +12 -0
  7. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +8 -0
  8. data/lib/foreman_inventory_upload/generators/archived_report.rb +6 -3
  9. data/lib/foreman_inventory_upload/generators/queries.rb +1 -0
  10. data/lib/foreman_inventory_upload/generators/slice.rb +20 -4
  11. data/lib/foreman_rh_cloud/engine.rb +4 -0
  12. data/lib/foreman_rh_cloud/version.rb +1 -1
  13. data/test/controllers/accounts_controller_test.rb +8 -3
  14. data/test/controllers/uploads_controller_test.rb +13 -0
  15. data/test/factories/inventory_upload_factories.rb +13 -13
  16. data/test/unit/slice_generator_test.rb +47 -4
  17. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +2 -0
  18. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +2 -1
  19. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListReducer.js +8 -0
  20. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListSelectors.js +2 -0
  21. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListReducer.test.js +11 -0
  22. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListSelectors.test.js +9 -1
  23. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +10 -0
  24. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +5 -2
  25. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.fixtures.js +1 -0
  26. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.js +32 -0
  27. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherActions.js +27 -0
  28. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherConstants.js +2 -0
  29. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/AutoUploadSwitcher.test.js +14 -0
  30. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/AutoUploadSwitcherActions.test.js +14 -0
  31. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcher.test.js.snap +38 -0
  32. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcherActions.test.js.snap +14 -0
  33. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/autoUploadSwitcher.scss +3 -0
  34. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/index.js +17 -0
  35. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardIntegration.test.js +2 -1
  36. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +21 -0
  37. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +13 -0
  38. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +33 -0
  39. data/webpack/ForemanInventoryUpload/Components/PageHeader/index.js +1 -0
  40. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/ScheduledRun.fixtures.js +1 -0
  41. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/ScheduledRun.js +4 -2
  42. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/__tests__/ScheduledRun.test.js +0 -1
  43. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/__tests__/__snapshots__/ScheduledRun.test.js.snap +0 -2
  44. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/index.js +12 -1
  45. data/webpack/ForemanInventoryUpload/Components/TabBody/__tests__/__snapshots__/TabBody.test.js.snap +1 -1
  46. data/webpack/ForemanInventoryUpload/ForemanInventoryUpload.js +5 -4
  47. data/webpack/ForemanInventoryUpload/__snapshots__/ForemanInventoryUpload.test.js.snap +6 -5
  48. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f6361a25739c19a67518378257d51f67fc443839d76d7d07f5bd597f09ef15d
4
- data.tar.gz: b558ad39920b634ee4c9be77ec20f65235eb3193de374879dc85bc284a15bfa5
3
+ metadata.gz: aa962e3bc67676bb6d21b2196824ddef35ece66d0b24dad52658605446c39dfb
4
+ data.tar.gz: 8ee5a01dda9593c05b2babe5f65ee31a8a88dded967b159972351b5ee07e518a
5
5
  SHA512:
6
- metadata.gz: 83b2169b736d8c57d544b8ce53bda7e91e4741efdd384953fd32a22ac96e531282e97ef740112a7be5310ef44fc0569fe8995972304844302d0b2eb3db6215f8
7
- data.tar.gz: 3b7bbd7d76a68b5b41874472961eabd2360de0ad871705430d7549d8c44b48e5811ba9d566d74a3c0a8774b7c3b4c0c5a0f75ae57f2f38519ef528e12239c4f3
6
+ metadata.gz: 6d766ae3c9edec7b7041c73058a80c1e268e5dd2323a049fe66963ab7f313e9ce54e4e6f677b022f2c630944b9b8278bac30207fe4b1cf278cd8db3bdaa393cf
7
+ data.tar.gz: 4e4b112121137835a8a54dd3831ff293e7ba172458a1de2adb310a73afcbb605fc48bfe80456fc7e640218a051d419a98d5e0537f5fa4455ed619de110632fa8
@@ -25,6 +25,7 @@ module ForemanInventoryUpload
25
25
  ]
26
26
 
27
27
  render json: {
28
+ autoUploadEnabled: Setting[:allow_auto_inventory_upload],
28
29
  accounts: accounts,
29
30
  }, status: :ok
30
31
  end
@@ -11,14 +11,10 @@ module ForemanInventoryUpload
11
11
 
12
12
  def download_file
13
13
  filename = ForemanInventoryUpload.facts_archive_name(params[:organization_id])
14
- path = Rails.root.join(ForemanInventoryUpload.uploads_folder, filename)
15
- unless File.exist? path
16
- return throw_flash_error(
17
- "Path doesn't exist: #{path}"
18
- )
19
- end
14
+ files = Dir["{#{ForemanInventoryUpload.uploads_file_path(filename)},#{ForemanInventoryUpload.done_file_path(filename)}}"]
20
15
 
21
- send_file path, disposition: 'attachment', filename: filename
16
+ return send_file files.first, disposition: 'attachment', filename: filename unless files.empty?
17
+ throw_flash_error "File doesn't exist"
22
18
  end
23
19
 
24
20
  def throw_flash_error(message)
@@ -27,5 +23,16 @@ module ForemanInventoryUpload
27
23
  :error_msg => message
28
24
  )
29
25
  end
26
+
27
+ def auto_upload
28
+ Setting[:allow_auto_inventory_upload] = auto_upload_params
29
+ render json: {
30
+ autoUploadEnabled: Setting[:allow_auto_inventory_upload],
31
+ }
32
+ end
33
+
34
+ def auto_upload_params
35
+ ActiveModel::Type::Boolean.new.cast(params.require(:value))
36
+ end
30
37
  end
31
38
  end
@@ -0,0 +1,13 @@
1
+ class Setting::RhCloud < Setting
2
+ def self.default_settings
3
+ return unless ActiveRecord::Base.connection.table_exists?('settings')
4
+ return unless super
5
+ [
6
+ set('allow_auto_inventory_upload', N_('Allow automatic upload of the host inventory to the Red Hat cloud'), true),
7
+ ]
8
+ end
9
+
10
+ def self.humanized_category
11
+ N_('RH Cloud')
12
+ end
13
+ end
@@ -6,5 +6,6 @@ Rails.application.routes.draw do
6
6
  get ':organization_id/uploads/last', to: 'uploads#last', constraints: { organization_id: %r{[^\/]+} }
7
7
  get ':organization_id/uploads/file', to: 'uploads#download_file', constraints: { organization_id: %r{[^\/]+} }
8
8
  get 'accounts', to: 'accounts#index'
9
+ post 'auto_upload', to: 'uploads#auto_upload'
9
10
  end
10
11
  end
@@ -18,6 +18,18 @@ module ForemanInventoryUpload
18
18
  )
19
19
  end
20
20
 
21
+ def self.uploads_file_path(filename)
22
+ File.join(ForemanInventoryUpload.uploads_folder, filename)
23
+ end
24
+
25
+ def self.done_folder
26
+ File.join(ForemanInventoryUpload.uploads_folder, 'done/')
27
+ end
28
+
29
+ def self.done_file_path(filename)
30
+ File.join(ForemanInventoryUpload.done_folder, filename)
31
+ end
32
+
21
33
  def self.generated_reports_folder
22
34
  @generated_reports_folder ||= ensure_folder(
23
35
  File.join(
@@ -2,6 +2,14 @@ module ForemanInventoryUpload
2
2
  module Async
3
3
  class GenerateAllReportsJob < ::ApplicationJob
4
4
  def perform
5
+ unless Setting[:allow_auto_inventory_upload]
6
+ logger.debug(
7
+ 'The scheduled process is disabled due to the "allow_auto_inventory_upload"
8
+ setting being set to false.'
9
+ )
10
+ return
11
+ end
12
+
5
13
  organizations = Organization.unscoped.all
6
14
 
7
15
  organizations.map do |organization|
@@ -16,9 +16,9 @@ module ForemanInventoryUpload
16
16
  first = true
17
17
  host_batches.each do |hosts_batch|
18
18
  slice_id = Foreman.uuid
19
- hosts_count = hosts_batch.count
20
- @logger.info "Adding slice #{slice_id} with #{hosts_count} hosts"
21
- generate_slice(tmpdir, slice_id, hosts_batch)
19
+ @logger.info "Adding slice #{slice_id}"
20
+ hosts_count = generate_slice(tmpdir, slice_id, hosts_batch)
21
+ @logger.info "slice #{slice_id} was created with #{hosts_count} hosts"
22
22
  inner_generator.add_slice(slice_id, hosts_count, first)
23
23
  first = false
24
24
  end
@@ -43,10 +43,13 @@ module ForemanInventoryUpload
43
43
  private
44
44
 
45
45
  def generate_slice(tmpdir, slice_id, hosts_batch)
46
+ hosts_count = 0
46
47
  File.open(File.join(tmpdir, "#{slice_id}.json"), 'w') do |slice_out|
47
48
  slice_generator = ForemanInventoryUpload::Generators::Slice.new(hosts_batch, slice_out, slice_id)
48
49
  slice_generator.render
50
+ hosts_count = slice_generator.hosts_count
49
51
  end
52
+ hosts_count
50
53
  end
51
54
  end
52
55
  end
@@ -18,6 +18,7 @@ module ForemanInventoryUpload
18
18
  'uname::release',
19
19
  'lscpu::flags',
20
20
  'distribution::version',
21
+ 'distribution::id',
21
22
  ]).pluck(:name, :id)
22
23
  ]
23
24
  end
@@ -4,11 +4,13 @@ module ForemanInventoryUpload
4
4
  include FactHelpers
5
5
 
6
6
  attr_accessor :slice_id
7
+ attr_reader :hosts_count
7
8
 
8
9
  def initialize(hosts, output = [], slice_id = Foreman.uuid)
9
10
  @stream = JsonStream.new(output)
10
11
  @hosts = hosts
11
12
  @slice_id = slice_id
13
+ @hosts_count = 0
12
14
  end
13
15
 
14
16
  def render
@@ -26,7 +28,10 @@ module ForemanInventoryUpload
26
28
  hosts_batch.each do |host|
27
29
  next unless host&.subscription_facet&.pools&.first
28
30
  @stream.comma unless first
29
- first = false if report_host(host)
31
+ if report_host(host)
32
+ first = false
33
+ @hosts_count += 1
34
+ end
30
35
  end
31
36
  end
32
37
  end
@@ -36,7 +41,7 @@ module ForemanInventoryUpload
36
41
  @stream.object do
37
42
  @stream.simple_field('display_name', host.name)
38
43
  @stream.simple_field('fqdn', host.fqdn)
39
- @stream.simple_field('account', host.subscription_facet.pools.first.account_number.to_s)
44
+ @stream.simple_field('account', host.subscription_facet.pools.where.not(account_number: nil).first&.account_number&.to_s)
40
45
  @stream.simple_field('subscription_manager_id', host.subscription_facet.uuid)
41
46
  @stream.simple_field('satellite_id', host.subscription_facet.uuid)
42
47
  @stream.simple_field('bios_uuid', fact_value(host, 'dmi::system::uuid'))
@@ -65,7 +70,7 @@ module ForemanInventoryUpload
65
70
 
66
71
  @stream.array_field('tags', :last) do
67
72
  report_tag('satellite', 'satellite_instance_id', Foreman.instance_id) if Foreman.respond_to?(:instance_id)
68
- report_tag('satellite', 'organization_id', host.organization_id, :last)
73
+ report_tag('satellite', 'organization_id', host.organization_id.to_s, :last)
69
74
  end
70
75
  end
71
76
  end
@@ -105,7 +110,14 @@ module ForemanInventoryUpload
105
110
  end.join(', '))
106
111
  end
107
112
  end
108
- @stream.simple_field('os_release', fact_value(host, 'distribution::name'))
113
+ @stream.simple_field(
114
+ 'os_release',
115
+ os_release_value(
116
+ name: fact_value(host, 'distribution::name'),
117
+ version: fact_value(host, 'distribution::version'),
118
+ codename: fact_value(host, 'distribution::id')
119
+ )
120
+ )
109
121
  @stream.simple_field('os_kernel_version', fact_value(host, 'uname::release'))
110
122
  @stream.simple_field('arch', host.architecture&.name)
111
123
  @stream.simple_field('subscription_status', host.subscription_status_label)
@@ -142,6 +154,10 @@ module ForemanInventoryUpload
142
154
  @stream.simple_field('satellite_instance_id', Foreman.respond_to?(:instance_id) ? Foreman.instance_id : nil)
143
155
  @stream.simple_field('organization_id', host.organization_id, :last)
144
156
  end
157
+
158
+ def os_release_value(name:, version:, codename:)
159
+ "#{name} #{version} (#{codename})"
160
+ end
145
161
  end
146
162
  end
147
163
  end
@@ -5,6 +5,10 @@ module ForemanRhCloud
5
5
  class Engine < ::Rails::Engine
6
6
  engine_name 'foreman_rh_cloud'
7
7
 
8
+ initializer 'foreman_rh_cloud.load_default_settings', :before => :load_config_initializers do
9
+ require_dependency File.expand_path('../../app/models/setting/rh_cloud.rb', __dir__)
10
+ end
11
+
8
12
  config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
9
13
  config.autoload_paths += Dir["#{config.root}/app/helpers/concerns"]
10
14
  config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '2.0.4'.freeze
2
+ VERSION = '2.0.5'.freeze
3
3
  end
@@ -14,12 +14,17 @@ class AccountsControllerTest < ActionController::TestCase
14
14
  upload_label = ForemanInventoryUpload::Async::UploadReportJob.output_label(test_org.id)
15
15
  upload_output = ForemanInventoryUpload::Async::ProgressOutput.register(upload_label)
16
16
  upload_output.status = 'upload_status_test'
17
+ FactoryBot.create(:setting, :name => 'allow_auto_inventory_upload', :value => true)
18
+ assert_equal true, Setting[:allow_auto_inventory_upload]
17
19
 
18
20
  get :index, session: set_session_user
19
21
 
20
22
  assert_response :success
21
- actual = JSON.parse(response.body)['accounts'][test_org.id.to_s]
22
- assert_equal 'generate_status_test', actual['generate_report_status']
23
- assert_equal 'upload_status_test', actual['upload_report_status']
23
+ actual = JSON.parse(response.body)
24
+ actual_account_statuses = actual['accounts'][test_org.id.to_s]
25
+ assert_equal 'generate_status_test', actual_account_statuses['generate_report_status']
26
+ assert_equal 'upload_status_test', actual_account_statuses['upload_report_status']
27
+
28
+ assert_equal true, actual['autoUploadEnabled']
24
29
  end
25
30
  end
@@ -18,4 +18,17 @@ class UploadsControllerTest < ActionController::TestCase
18
18
  actual = JSON.parse(response.body)
19
19
  assert_equal 'test output', actual['output']
20
20
  end
21
+
22
+ test 'should update allow_auto_inventory_upload setting' do
23
+ FactoryBot.create(:setting, :name => 'allow_auto_inventory_upload', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
24
+
25
+ assert_equal false, Setting[:allow_auto_inventory_upload]
26
+
27
+ post :auto_upload, params: { value: true }, session: set_session_user
28
+
29
+ assert_response :success
30
+ actual = JSON.parse(response.body)
31
+ assert_equal true, actual['autoUploadEnabled']
32
+ assert_equal true, Setting[:allow_auto_inventory_upload]
33
+ end
21
34
  end
@@ -1,16 +1,16 @@
1
1
  # redefine katello factories, as long as katello is not compatible with dynamic properties
2
2
  FactoryBot.define do
3
3
  factory :katello_organization, :class => "Organization" do
4
- type {"Organization"}
4
+ type { "Organization" }
5
5
  sequence(:name) { |n| "Organization#{n}" }
6
6
  sequence(:label) { |n| "org#{n}" }
7
7
  sequence(:id) { |n| n }
8
8
 
9
9
  trait :acme_corporation do
10
- name {"ACME_Corporation"}
11
- type {"Organization"}
12
- description {"This is the first Organization."}
13
- label {"acme_corporation_label"}
10
+ name { "ACME_Corporation" }
11
+ type { "Organization" }
12
+ description { "This is the first Organization." }
13
+ label { "acme_corporation_label" }
14
14
  end
15
15
 
16
16
  trait :with_library do
@@ -24,11 +24,11 @@ end
24
24
  FactoryBot.define do
25
25
  factory :katello_content_view, :class => Katello::ContentView do
26
26
  sequence(:name) { |n| "Database#{n}" }
27
- description {"This content view is for database content"}
27
+ description { "This content view is for database content" }
28
28
  association :organization, :factory => :katello_organization
29
29
 
30
30
  trait :composite do
31
- composite {true}
31
+ composite { true }
32
32
  end
33
33
  end
34
34
  end
@@ -50,23 +50,23 @@ end
50
50
  FactoryBot.define do
51
51
  factory :katello_subscription_facets, :aliases => [:subscription_facet], :class => ::Katello::Host::SubscriptionFacet do
52
52
  sequence(:uuid) { |n| "uuid-#{n}-#{rand(500)}" }
53
- facts { {'memory.memtotal' => "12 GB"} }
53
+ facts { { 'memory.memtotal' => "12 GB" } }
54
54
  end
55
55
  end
56
56
 
57
57
  FactoryBot.define do
58
58
  factory :katello_pool, :class => Katello::Pool do
59
- active {true}
60
- end_date {Date.today + 1.year}
59
+ active { true }
60
+ end_date { Date.today + 1.year }
61
61
  end
62
62
  end
63
63
 
64
64
  FactoryBot.modify do
65
65
  factory :host do
66
66
  transient do
67
- content_view {nil}
68
- lifecycle_environment {nil}
69
- content_source {nil}
67
+ content_view { nil }
68
+ lifecycle_environment { nil }
69
+ content_source { nil }
70
70
  end
71
71
 
72
72
  trait :with_content do
@@ -17,6 +17,8 @@ class ReportGeneratorTest < ActiveSupport::TestCase
17
17
  )
18
18
 
19
19
  @host.subscription_facet.pools << FactoryBot.create(:katello_pool, account_number: '1234', cp_id: 1)
20
+
21
+ ForemanInventoryUpload::Generators::Queries.instance_variable_set(:@fact_names, nil)
20
22
  end
21
23
 
22
24
  def interesting_facts
@@ -30,9 +32,11 @@ class ReportGeneratorTest < ActiveSupport::TestCase
30
32
  'dmi::bios::vendor',
31
33
  'dmi::bios::version',
32
34
  'dmi::bios::relase_date',
33
- 'distribution::name',
34
35
  'uname::release',
35
36
  'lscpu::flags',
37
+ 'distribution::name',
38
+ 'distribution::version',
39
+ 'distribution::id',
36
40
  ]
37
41
  end
38
42
 
@@ -56,6 +60,7 @@ class ReportGeneratorTest < ActiveSupport::TestCase
56
60
  assert_equal @host.name, actual_host['display_name']
57
61
  assert_equal @host.fqdn, actual_host['fqdn']
58
62
  assert_equal '1234', actual_host['account']
63
+ assert_equal 1, generator.hosts_count
59
64
  end
60
65
 
61
66
  test 'generates a report with satellite facts' do
@@ -72,13 +77,13 @@ class ReportGeneratorTest < ActiveSupport::TestCase
72
77
  assert_equal 'satellite-id', satellite_facts['satellite_instance_id']
73
78
  assert_equal @host.organization_id, satellite_facts['organization_id']
74
79
 
75
- instance_id_tag = actual['hosts'].first['tags'].find { |tag| tag['namespace'] == 'satellite' && tag['key'] == 'satellite_instance_id'}
80
+ instance_id_tag = actual['hosts'].first['tags'].find { |tag| tag['namespace'] == 'satellite' && tag['key'] == 'satellite_instance_id' }
76
81
  assert_not_nil instance_id_tag
77
82
  assert_equal 'satellite-id', instance_id_tag['value']
78
83
 
79
- org_id_tag = actual['hosts'].first['tags'].find { |tag| tag['namespace'] == 'satellite' && tag['key'] == 'organization_id'}
84
+ org_id_tag = actual['hosts'].first['tags'].find { |tag| tag['namespace'] == 'satellite' && tag['key'] == 'organization_id' }
80
85
  assert_not_nil org_id_tag
81
- assert_equal @host.organization_id, org_id_tag['value']
86
+ assert_equal @host.organization_id.to_s, org_id_tag['value']
82
87
 
83
88
  version = satellite_facts['satellite_version']
84
89
  if defined?(ForemanThemeSatellite)
@@ -158,6 +163,7 @@ class ReportGeneratorTest < ActiveSupport::TestCase
158
163
  assert_equal @host.name, actual_host['display_name']
159
164
  assert_equal @host.fqdn, actual_host['fqdn']
160
165
  assert_equal '1234', actual_host['account']
166
+ assert_equal 1, generator.hosts_count
161
167
  end
162
168
 
163
169
  test 'shows system_memory_bytes in bytes' do
@@ -174,4 +180,41 @@ class ReportGeneratorTest < ActiveSupport::TestCase
174
180
  assert_not_nil(actual_profile = actual_host['system_profile'])
175
181
  assert_equal 1024, actual_profile['system_memory_bytes']
176
182
  end
183
+
184
+ test 'reports an account for hosts with multiple pools' do
185
+ first_pool = @host.subscription_facet.pools.first
186
+ second_pool = FactoryBot.create(:katello_pool, account_number: nil, cp_id: 2)
187
+ @host.subscription_facet.pools = []
188
+ @host.subscription_facet.save!
189
+ @host.subscription_facet.pools << first_pool
190
+ @host.subscription_facet.pools << second_pool
191
+
192
+ batch = Host.where(id: @host.id).in_batches.first
193
+ generator = ForemanInventoryUpload::Generators::Slice.new(batch, [], 'slice_123')
194
+
195
+ json_str = generator.render
196
+ actual = JSON.parse(json_str.join("\n"))
197
+
198
+ assert_equal 'slice_123', actual['report_slice_id']
199
+ assert_not_nil(actual_host = actual['hosts'].first)
200
+ assert_not_nil(actual_host['account'])
201
+ assert_not_empty(actual_host['account'])
202
+ end
203
+
204
+ test 'Generates os_release with version and id' do
205
+ FactoryBot.create(:fact_value, fact_name: fact_names['distribution::name'], value: 'Red Hat Test Linux', host: @host)
206
+ FactoryBot.create(:fact_value, fact_name: fact_names['distribution::version'], value: '7.1', host: @host)
207
+ FactoryBot.create(:fact_value, fact_name: fact_names['distribution::id'], value: 'TestId', host: @host)
208
+
209
+ batch = Host.where(id: @host.id).in_batches.first
210
+ generator = ForemanInventoryUpload::Generators::Slice.new(batch, [], 'slice_123')
211
+
212
+ json_str = generator.render
213
+ actual = JSON.parse(json_str.join("\n"))
214
+
215
+ assert_equal 'slice_123', actual['report_slice_id']
216
+ assert_not_nil(actual_host = actual['hosts'].first)
217
+ assert_not_nil(actual_profile = actual_host['system_profile'])
218
+ assert_equal 'Red Hat Test Linux 7.1 (TestId)', actual_profile['os_release']
219
+ end
177
220
  end
@@ -28,6 +28,8 @@ export const accountID = 'user@redhat.com';
28
28
 
29
29
  export const processStatusName = 'upload_report_status';
30
30
 
31
+ export const autoUploadEnabled = true;
32
+
31
33
  export const props = {
32
34
  accounts,
33
35
  fetchAccountsStatus: noop,
@@ -10,12 +10,13 @@ import {
10
10
  export const fetchAccountsStatus = () => async dispatch => {
11
11
  try {
12
12
  const {
13
- data: { accounts },
13
+ data: { accounts, autoUploadEnabled },
14
14
  } = await API.get('accounts');
15
15
  dispatch({
16
16
  type: INVENTORY_ACCOUNT_STATUS_POLLING,
17
17
  payload: {
18
18
  accounts,
19
+ autoUploadEnabled,
19
20
  },
20
21
  });
21
22
  } catch (error) {
@@ -5,6 +5,7 @@ import {
5
5
  INVENTORY_ACCOUNT_STATUS_POLLING_START,
6
6
  INVENTORY_PROCESS_RESTART,
7
7
  } from './AccountListConstants';
8
+ import { AUTO_UPLOAD_TOGGLE } from '../AutoUploadSwitcher/AutoUploadSwitcherConstants';
8
9
 
9
10
  const initialState = Immutable({
10
11
  accounts: {},
@@ -20,6 +21,7 @@ export default (state = initialState, action) => {
20
21
  accounts,
21
22
  accountID,
22
23
  processStatusName,
24
+ autoUploadEnabled,
23
25
  } = {},
24
26
  } = action;
25
27
 
@@ -28,6 +30,7 @@ export default (state = initialState, action) => {
28
30
  return state.merge({
29
31
  ...state,
30
32
  accounts,
33
+ autoUploadEnabled,
31
34
  error: null,
32
35
  });
33
36
  case INVENTORY_ACCOUNT_STATUS_POLLING_ERROR:
@@ -49,6 +52,11 @@ export default (state = initialState, action) => {
49
52
  [processStatusName]: 'Restarting...',
50
53
  },
51
54
  });
55
+ case AUTO_UPLOAD_TOGGLE:
56
+ return state.merge({
57
+ ...state,
58
+ autoUploadEnabled,
59
+ });
52
60
  default:
53
61
  return state;
54
62
  }
@@ -6,3 +6,5 @@ export const selectAccounts = state => selectAccountsList(state).accounts;
6
6
  export const selectPollingProcessID = state =>
7
7
  selectAccountsList(state).pollingProcessID;
8
8
  export const selectError = state => selectAccountsList(state).error;
9
+ export const selectAutoUploadEnabled = state =>
10
+ selectAccountsList(state).autoUploadEnabled;
@@ -14,7 +14,9 @@ import {
14
14
  pollingProcessID,
15
15
  accountID,
16
16
  processStatusName,
17
+ autoUploadEnabled,
17
18
  } from '../AccountList.fixtures';
19
+ import { AUTO_UPLOAD_TOGGLE } from '../../AutoUploadSwitcher/AutoUploadSwitcherConstants';
18
20
 
19
21
  const fixtures = {
20
22
  'should return the initial state': {},
@@ -23,6 +25,7 @@ const fixtures = {
23
25
  type: INVENTORY_ACCOUNT_STATUS_POLLING,
24
26
  payload: {
25
27
  accounts,
28
+ autoUploadEnabled,
26
29
  },
27
30
  },
28
31
  },
@@ -54,6 +57,14 @@ const fixtures = {
54
57
  },
55
58
  },
56
59
  },
60
+ 'should handle AUTO_UPLOAD_TOGGLE': {
61
+ action: {
62
+ type: AUTO_UPLOAD_TOGGLE,
63
+ payload: {
64
+ autoUploadEnabled,
65
+ },
66
+ },
67
+ },
57
68
  };
58
69
 
59
70
  describe('AccountList reducer', () =>
@@ -3,14 +3,20 @@ import {
3
3
  selectAccountsList,
4
4
  selectAccounts,
5
5
  selectPollingProcessID,
6
+ selectAutoUploadEnabled,
6
7
  } from '../AccountListSelectors';
7
- import { pollingProcessID, accounts } from '../AccountList.fixtures';
8
+ import {
9
+ pollingProcessID,
10
+ accounts,
11
+ autoUploadEnabled,
12
+ } from '../AccountList.fixtures';
8
13
 
9
14
  const state = {
10
15
  ForemanInventoryUpload: {
11
16
  accountsList: {
12
17
  accounts,
13
18
  pollingProcessID,
19
+ autoUploadEnabled,
14
20
  },
15
21
  },
16
22
  };
@@ -20,6 +26,8 @@ const fixtures = {
20
26
  'should return AccountList accounts': () => selectAccounts(state),
21
27
  'should return AccountList pollingProcessID': () =>
22
28
  selectPollingProcessID(state),
29
+ 'should return AccountList autoUploadEnabled': () =>
30
+ selectAutoUploadEnabled(state),
23
31
  };
24
32
 
25
33
  describe('AccountList selectors', () =>
@@ -1,5 +1,14 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`AccountList reducer should handle AUTO_UPLOAD_TOGGLE 1`] = `
4
+ Object {
5
+ "accounts": Object {},
6
+ "autoUploadEnabled": true,
7
+ "error": null,
8
+ "pollingProcessID": 0,
9
+ }
10
+ `;
11
+
3
12
  exports[`AccountList reducer should handle INVENTORY_ACCOUNT_STATUS_POLLING 1`] = `
4
13
  Object {
5
14
  "accounts": Object {
@@ -19,6 +28,7 @@ Object {
19
28
  "upload_report_status": "success",
20
29
  },
21
30
  },
31
+ "autoUploadEnabled": true,
22
32
  "error": null,
23
33
  "pollingProcessID": 0,
24
34
  }
@@ -1,7 +1,5 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`AccountList selectors should return AccountList pollingProcessID 1`] = `0`;
4
-
5
3
  exports[`AccountList selectors should return AccountList accounts 1`] = `
6
4
  Object {
7
5
  "Account1": Object {
@@ -22,6 +20,10 @@ Object {
22
20
  }
23
21
  `;
24
22
 
23
+ exports[`AccountList selectors should return AccountList autoUploadEnabled 1`] = `true`;
24
+
25
+ exports[`AccountList selectors should return AccountList pollingProcessID 1`] = `0`;
26
+
25
27
  exports[`AccountList selectors should return AccountsList 1`] = `
26
28
  Object {
27
29
  "accounts": Object {
@@ -41,6 +43,7 @@ Object {
41
43
  "upload_report_status": "success",
42
44
  },
43
45
  },
46
+ "autoUploadEnabled": true,
44
47
  "pollingProcessID": 0,
45
48
  }
46
49
  `;
@@ -0,0 +1 @@
1
+ export const handleToggleResponse = { data: { autoUploadEnabled: true } };
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Switch, FieldLevelHelp } from 'patternfly-react';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+ import './autoUploadSwitcher.scss';
6
+
7
+ const AutoUploadSwitcher = ({ autoUploadEnabled, handleToggle }) => (
8
+ <div className="auto_upload_switcher">
9
+ <Switch
10
+ size="mini"
11
+ value={autoUploadEnabled}
12
+ onChange={() => handleToggle(autoUploadEnabled)}
13
+ />
14
+ <FieldLevelHelp
15
+ content={__(
16
+ 'Enable automatic upload of your host inventory to the Red Hat cloud'
17
+ )}
18
+ />
19
+ <span>Allow Auto Upload</span>
20
+ </div>
21
+ );
22
+
23
+ AutoUploadSwitcher.propTypes = {
24
+ autoUploadEnabled: PropTypes.bool,
25
+ handleToggle: PropTypes.func.isRequired,
26
+ };
27
+
28
+ AutoUploadSwitcher.defaultProps = {
29
+ autoUploadEnabled: true,
30
+ };
31
+
32
+ export default AutoUploadSwitcher;
@@ -0,0 +1,27 @@
1
+ import API from 'foremanReact/API';
2
+ import {
3
+ AUTO_UPLOAD_TOGGLE,
4
+ AUTO_UPLOAD_TOGGLE_ERROR,
5
+ } from './AutoUploadSwitcherConstants';
6
+
7
+ export const handleToggle = currentAutoUploadEnabled => async dispatch => {
8
+ const toggledAutoUploadEnabled = !currentAutoUploadEnabled;
9
+ try {
10
+ const {
11
+ data: { autoUploadEnabled },
12
+ } = await API.post('auto_upload', { value: toggledAutoUploadEnabled });
13
+ dispatch({
14
+ type: AUTO_UPLOAD_TOGGLE,
15
+ payload: {
16
+ autoUploadEnabled,
17
+ },
18
+ });
19
+ } catch (error) {
20
+ dispatch({
21
+ type: AUTO_UPLOAD_TOGGLE_ERROR,
22
+ payload: {
23
+ error: error.message,
24
+ },
25
+ });
26
+ }
27
+ };
@@ -0,0 +1,2 @@
1
+ export const AUTO_UPLOAD_TOGGLE = 'AUTO_UPLOAD_TOGGLE';
2
+ export const AUTO_UPLOAD_TOGGLE_ERROR = 'AUTO_UPLOAD_TOGGLE_ERROR';
@@ -0,0 +1,14 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import { noop } from 'patternfly-react';
3
+
4
+ import AutoUploadSwitcher from '../AutoUploadSwitcher';
5
+
6
+ const fixtures = {
7
+ 'render with props': { autoUploadEnabled: true, handleToggle: noop },
8
+ /** fixtures, props for the component */
9
+ };
10
+
11
+ describe('AutoUploadSwitcher', () => {
12
+ describe('rendering', () =>
13
+ testComponentSnapshotsWithFixtures(AutoUploadSwitcher, fixtures));
14
+ });
@@ -0,0 +1,14 @@
1
+ import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
+ import API from 'foremanReact/API';
3
+ import { handleToggle } from '../AutoUploadSwitcherActions';
4
+ import { handleToggleResponse } from '../AutoUploadSwitcher.fixtures';
5
+
6
+ jest.mock('foremanReact/API');
7
+ API.post.mockImplementation(async () => handleToggleResponse);
8
+
9
+ const fixtures = {
10
+ 'should handleToggle': () => handleToggle(),
11
+ };
12
+
13
+ describe('AutoUploadSwitcher actions', () =>
14
+ testActionSnapshotWithFixtures(fixtures));
@@ -0,0 +1,38 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`AutoUploadSwitcher rendering render with props 1`] = `
4
+ <div
5
+ className="auto_upload_switcher"
6
+ >
7
+ <Switch
8
+ animate={true}
9
+ baseClass="bootstrap-switch"
10
+ bsSize={null}
11
+ defaultValue={true}
12
+ disabled={false}
13
+ handleWidth="auto"
14
+ inverse={false}
15
+ labelText=" "
16
+ labelWidth="auto"
17
+ offColor="default"
18
+ offText="OFF"
19
+ onChange={[Function]}
20
+ onColor="primary"
21
+ onText="ON"
22
+ readonly={false}
23
+ size="mini"
24
+ tristate={false}
25
+ value={true}
26
+ wrapperClass="wrapper"
27
+ />
28
+ <FieldLevelHelp
29
+ buttonClass=""
30
+ content="Enable automatic upload of your host inventory to the Red Hat cloud"
31
+ placement="top"
32
+ rootClose={true}
33
+ />
34
+ <span>
35
+ Allow Auto Upload
36
+ </span>
37
+ </div>
38
+ `;
@@ -0,0 +1,14 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`AutoUploadSwitcher actions should handleToggle 1`] = `
4
+ Array [
5
+ Array [
6
+ Object {
7
+ "payload": Object {
8
+ "autoUploadEnabled": true,
9
+ },
10
+ "type": "AUTO_UPLOAD_TOGGLE",
11
+ },
12
+ ],
13
+ ]
14
+ `;
@@ -0,0 +1,3 @@
1
+ .auto_upload_switcher {
2
+ float: right;
3
+ }
@@ -0,0 +1,17 @@
1
+ import { bindActionCreators } from 'redux';
2
+ import { connect } from 'react-redux';
3
+
4
+ import * as actions from './AutoUploadSwitcherActions';
5
+ import AutoUploadSwitcher from './AutoUploadSwitcher';
6
+ import { selectAutoUploadEnabled } from '../AccountList/AccountListSelectors';
7
+
8
+ // map state to props
9
+ const mapStateToProps = state => ({
10
+ autoUploadEnabled: selectAutoUploadEnabled(state),
11
+ });
12
+
13
+ // map action dispatchers to props
14
+ const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
15
+
16
+ // export connected component
17
+ export default connect(mapStateToProps, mapDispatchToProps)(AutoUploadSwitcher);
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  import { IntegrationTestHelper } from '@theforeman/test';
3
3
 
4
- import Dashboard, { reducers } from '../index';
4
+ import Dashboard from '../Dashboard';
5
+ import reducers from '../../../ForemanInventoryUploadReducers';
5
6
  import { accountID } from '../Dashboard.fixtures';
6
7
 
7
8
  describe('Dashboard integration test', () => {
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { Grid } from 'patternfly-react';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import AutoUploadSwitcher from '../AutoUploadSwitcher';
5
+
6
+ const PageHeader = () => (
7
+ <React.Fragment>
8
+ <Grid.Row>
9
+ <Grid.Col xs={12}>
10
+ <h1>{__('Red Hat Inventory Uploads')}</h1>
11
+ </Grid.Col>
12
+ </Grid.Row>
13
+ <Grid.Row>
14
+ <Grid.Col xs={4} xsOffset={8}>
15
+ <AutoUploadSwitcher />
16
+ </Grid.Col>
17
+ </Grid.Row>
18
+ </React.Fragment>
19
+ );
20
+
21
+ export default PageHeader;
@@ -0,0 +1,13 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+
3
+ import PageHeader from '../PageHeader';
4
+
5
+ const fixtures = {
6
+ 'render without Props': {},
7
+ /** fixtures, props for the component */
8
+ };
9
+
10
+ describe('PageHeader', () => {
11
+ describe('rendering', () =>
12
+ testComponentSnapshotsWithFixtures(PageHeader, fixtures));
13
+ });
@@ -0,0 +1,33 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`PageHeader rendering render without Props 1`] = `
4
+ <Fragment>
5
+ <Row
6
+ bsClass="row"
7
+ componentClass="div"
8
+ >
9
+ <Col
10
+ bsClass="col"
11
+ componentClass="div"
12
+ xs={12}
13
+ >
14
+ <h1>
15
+ Red Hat Inventory Uploads
16
+ </h1>
17
+ </Col>
18
+ </Row>
19
+ <Row
20
+ bsClass="row"
21
+ componentClass="div"
22
+ >
23
+ <Col
24
+ bsClass="col"
25
+ componentClass="div"
26
+ xs={4}
27
+ xsOffset={8}
28
+ >
29
+ <Connect(AutoUploadSwitcher) />
30
+ </Col>
31
+ </Row>
32
+ </Fragment>
33
+ `;
@@ -0,0 +1 @@
1
+ export { default } from './PageHeader';
@@ -1,3 +1,4 @@
1
1
  export const props = {
2
2
  date: '2019-08-21T16:14:16.520+03:00',
3
+ autoUploadEnabled: true,
3
4
  };
@@ -5,8 +5,8 @@ import { FormattedRelative } from 'react-intl';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
6
  import './scheduledRun.scss';
7
7
 
8
- const ScheduledRun = ({ date }) =>
9
- date ? (
8
+ const ScheduledRun = ({ date, autoUploadEnabled }) =>
9
+ autoUploadEnabled && date ? (
10
10
  <Grid.Col sm={12} className="scheduled_run">
11
11
  <p>
12
12
  <Icon name="calendar" />
@@ -18,10 +18,12 @@ const ScheduledRun = ({ date }) =>
18
18
 
19
19
  ScheduledRun.propTypes = {
20
20
  date: PropTypes.string,
21
+ autoUploadEnabled: PropTypes.bool,
21
22
  };
22
23
 
23
24
  ScheduledRun.defaultProps = {
24
25
  date: null,
26
+ autoUploadEnabled: true,
25
27
  };
26
28
 
27
29
  export default ScheduledRun;
@@ -4,7 +4,6 @@ import ScheduledRun from '../ScheduledRun';
4
4
  import { props } from '../ScheduledRun.fixtures';
5
5
 
6
6
  const fixtures = {
7
- 'render without Props': {},
8
7
  'render with Props': props,
9
8
  };
10
9
 
@@ -21,5 +21,3 @@ exports[`ScheduledRun rendering render with Props 1`] = `
21
21
  </p>
22
22
  </Col>
23
23
  `;
24
-
25
- exports[`ScheduledRun rendering render without Props 1`] = `""`;
@@ -1 +1,12 @@
1
- export { default } from './ScheduledRun';
1
+ import { connect } from 'react-redux';
2
+
3
+ import ScheduledRun from './ScheduledRun';
4
+ import { selectAutoUploadEnabled } from '../AccountList/AccountListSelectors';
5
+
6
+ // map state to props
7
+ const mapStateToProps = state => ({
8
+ autoUploadEnabled: selectAutoUploadEnabled(state),
9
+ });
10
+
11
+ // export connected component
12
+ export default connect(mapStateToProps)(ScheduledRun);
@@ -12,7 +12,7 @@ exports[`TabBody rendering render without Props 1`] = `
12
12
  exitCode=""
13
13
  logs={null}
14
14
  />
15
- <ScheduledRun
15
+ <Connect(ScheduledRun)
16
16
  date={null}
17
17
  />
18
18
  </Row>
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import { IntlProvider } from 'react-intl';
3
- import { translate as __ } from 'foremanReact/common/I18n';
3
+ import { Grid } from 'patternfly-react';
4
4
  import AccountList from './Components/AccountList';
5
+ import PageHeader from './Components/PageHeader';
5
6
 
6
7
  const ForemanInventoryUpload = () => (
7
8
  <IntlProvider locale={navigator.language}>
8
- <div className="inventory-upload">
9
- <h1>{__('Red Hat Inventory Uploads')}</h1>
9
+ <Grid fluid className="inventory-upload">
10
+ <PageHeader />
10
11
  <AccountList />
11
- </div>
12
+ </Grid>
12
13
  </IntlProvider>
13
14
  );
14
15
 
@@ -4,13 +4,14 @@ exports[`ForemanInventoryUpload render without Props 1`] = `
4
4
  <IntlProvider
5
5
  locale="en-US"
6
6
  >
7
- <div
7
+ <Grid
8
+ bsClass="container"
8
9
  className="inventory-upload"
10
+ componentClass="div"
11
+ fluid={true}
9
12
  >
10
- <h1>
11
- Red Hat Inventory Uploads
12
- </h1>
13
+ <PageHeader />
13
14
  <Connect(AccountList) />
14
- </div>
15
+ </Grid>
15
16
  </IntlProvider>
16
17
  `;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_rh_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-09 00:00:00.000000000 Z
11
+ date: 2020-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katello
@@ -109,6 +109,7 @@ files:
109
109
  - app/controllers/foreman_inventory_upload/reports_controller.rb
110
110
  - app/controllers/foreman_inventory_upload/uploads_controller.rb
111
111
  - app/helpers/foreman_inventory_upload_helper.rb
112
+ - app/models/setting/rh_cloud.rb
112
113
  - app/views/foreman_inventory_upload/layouts/react.html.erb
113
114
  - config/routes.rb
114
115
  - lib/foreman_inventory_upload.rb
@@ -191,6 +192,16 @@ files:
191
192
  - webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap
192
193
  - webpack/ForemanInventoryUpload/Components/AccountList/accountList.scss
193
194
  - webpack/ForemanInventoryUpload/Components/AccountList/index.js
195
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.fixtures.js
196
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.js
197
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherActions.js
198
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherConstants.js
199
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/AutoUploadSwitcher.test.js
200
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/AutoUploadSwitcherActions.test.js
201
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcher.test.js.snap
202
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcherActions.test.js.snap
203
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/autoUploadSwitcher.scss
204
+ - webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/index.js
194
205
  - webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.fixtures.js
195
206
  - webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js
196
207
  - webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.stories.js
@@ -231,6 +242,10 @@ files:
231
242
  - webpack/ForemanInventoryUpload/Components/NavContainer/__tests__/__snapshots__/NavContainer.test.js.snap
232
243
  - webpack/ForemanInventoryUpload/Components/NavContainer/index.js
233
244
  - webpack/ForemanInventoryUpload/Components/NavContainer/navContainer.scss
245
+ - webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js
246
+ - webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js
247
+ - webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap
248
+ - webpack/ForemanInventoryUpload/Components/PageHeader/index.js
234
249
  - webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.fixtures.js
235
250
  - webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.js
236
251
  - webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerateHelper.js