foreman_rh_cloud 0.9.8 → 0.9.13

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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -0
  3. data/app/controllers/foreman_inventory_upload/accounts_controller.rb +3 -0
  4. data/app/controllers/foreman_inventory_upload/tasks_controller.rb +25 -0
  5. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +18 -0
  6. data/app/controllers/insights_cloud/hits_controller.rb +17 -0
  7. data/app/controllers/insights_cloud/settings_controller.rb +24 -0
  8. data/app/controllers/insights_cloud/tasks_controller.rb +1 -2
  9. data/app/helpers/foreman_inventory_upload_host_helper.rb +10 -2
  10. data/app/models/concerns/rh_cloud_host.rb +15 -0
  11. data/app/models/insights_facet.rb +5 -1
  12. data/app/models/insights_hit.rb +1 -1
  13. data/app/models/inventory_sync/inventory_status.rb +30 -0
  14. data/app/models/setting/rh_cloud.rb +4 -1
  15. data/app/overrides/hosts_list.rb +1 -1
  16. data/app/services/foreman_rh_cloud/cloud_auth.rb +28 -0
  17. data/app/views/foreman_rh_cloud/react/insights_cloud.html.erb +6 -1
  18. data/app/views/foreman_rh_cloud/react/inventory_upload.html.erb +1 -1
  19. data/app/views/hosts/_insights_tab.html.erb +15 -0
  20. data/config/routes.rb +6 -0
  21. data/db/migrate/20200727111529_add_uuid_column_to_insights_facets.foreman_rh_cloud.rb +5 -0
  22. data/db/migrate/20201007115752_add_hits_count_to_insights_facets_table.foreman_rh_cloud.rb +5 -0
  23. data/db/migrate/20201007121540_setup_hits_count_cache.foreman_rh_cloud.rb +10 -0
  24. data/lib/foreman_inventory_upload.rb +4 -0
  25. data/lib/foreman_inventory_upload/async/generate_report_job.rb +1 -1
  26. data/lib/foreman_inventory_upload/async/shell_process.rb +15 -9
  27. data/lib/foreman_inventory_upload/async/upload_report_job.rb +21 -9
  28. data/lib/foreman_inventory_upload/generators/fact_helpers.rb +36 -1
  29. data/lib/foreman_inventory_upload/generators/json_stream.rb +17 -2
  30. data/lib/foreman_inventory_upload/generators/metadata.rb +3 -0
  31. data/lib/foreman_inventory_upload/generators/queries.rb +4 -4
  32. data/lib/foreman_inventory_upload/generators/slice.rb +62 -34
  33. data/lib/foreman_rh_cloud.rb +67 -0
  34. data/lib/foreman_rh_cloud/engine.rb +20 -3
  35. data/lib/foreman_rh_cloud/version.rb +1 -1
  36. data/lib/insights_cloud.rb +8 -8
  37. data/lib/insights_cloud/async/insights_full_sync.rb +24 -32
  38. data/lib/insights_cloud/async/insights_scheduled_sync.rb +23 -0
  39. data/lib/inventory_sync/async/host_result.rb +50 -0
  40. data/lib/inventory_sync/async/inventory_full_sync.rb +80 -0
  41. data/lib/tasks/insights.rake +15 -0
  42. data/lib/tasks/rh_cloud_inventory.rake +37 -0
  43. data/package.json +3 -1
  44. data/test/controllers/insights_sync/settings_controller_test.rb +30 -0
  45. data/test/factories/insights_factories.rb +31 -0
  46. data/test/jobs/insights_full_sync_test.rb +33 -1
  47. data/test/jobs/inventory_full_sync_test.rb +91 -0
  48. data/test/jobs/upload_report_job_test.rb +34 -0
  49. data/test/unit/fact_helpers_test.rb +22 -0
  50. data/test/unit/insights_facet_test.rb +23 -0
  51. data/test/unit/metadata_generator_test.rb +2 -0
  52. data/test/unit/rh_cloud_http_proxy_test.rb +52 -0
  53. data/test/unit/slice_generator_test.rb +173 -11
  54. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +16 -1
  55. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +22 -17
  56. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListReducer.js +18 -0
  57. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListSelectors.js +8 -0
  58. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListActions.test.js +7 -0
  59. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListReducer.test.js +12 -6
  60. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListSelectors.test.js +9 -0
  61. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListActions.test.js.snap +20 -0
  62. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +12 -0
  63. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +6 -0
  64. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.fixtures.js +2 -0
  65. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherActions.js +10 -11
  66. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcherConstants.js +0 -1
  67. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/AutoUploadSwitcherActions.test.js +12 -2
  68. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcherActions.test.js.snap +17 -0
  69. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/ExcludePackagesSwitcher.fixtures.js +1 -0
  70. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/ExcludePackagesSwitcher.js +30 -0
  71. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/ExcludePackagesSwitcherActions.js +29 -0
  72. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/ExcludePackagesSwitcherConstants.js +1 -0
  73. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/ExcludePackagesSwitcher.test.js +13 -0
  74. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/ExcludePackagesSwitcherActions.test.js +21 -0
  75. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/__snapshots__/ExcludePackagesSwitcher.test.js.snap +38 -0
  76. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/__snapshots__/ExcludePackagesSwitcherActions.test.js.snap +31 -0
  77. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/__snapshots__/integration.test.js.snap +41 -0
  78. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/__tests__/integration.test.js +38 -0
  79. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/excludePackagesSwitcher.scss +3 -0
  80. data/webpack/ForemanInventoryUpload/Components/ExcludePackagesSwitcher/index.js +20 -0
  81. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.js +5 -1
  82. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/__snapshots__/FullScreenModal.test.js.snap +1 -0
  83. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/fullScreenModal.scss +15 -13
  84. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcher.fixtures.js +2 -1
  85. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcher.js +1 -0
  86. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcher.scss +3 -0
  87. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcherActions.js +10 -11
  88. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcherConstants.js +0 -2
  89. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/HostObfuscationSwitcherActions.test.js +12 -2
  90. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/__snapshots__/HostObfuscationSwitcherActions.test.js.snap +18 -1
  91. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +9 -0
  92. data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.js +4 -0
  93. data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/__snapshots__/InventorySettings.test.js.snap +2 -0
  94. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/IpsObfuscationSwitcher.fixtures.js +1 -0
  95. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/IpsObfuscationSwitcher.js +29 -0
  96. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/IpsObfuscationSwitcherActions.js +29 -0
  97. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/IpsObfuscationSwitcherConstants.js +1 -0
  98. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/__tests__/IpsObfuscationSwitcher.test.js +13 -0
  99. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/__tests__/IpsObfuscationSwitcherActions.test.js +21 -0
  100. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/__tests__/__snapshots__/IpsObfuscationSwitcher.test.js.snap +38 -0
  101. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/__tests__/__snapshots__/IpsObfuscationSwitcherActions.test.js.snap +31 -0
  102. data/webpack/ForemanInventoryUpload/Components/IpsObfuscationSwitcher/index.js +20 -0
  103. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +1 -1
  104. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +3 -3
  105. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/DocsButton.js +1 -0
  106. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/__tests__/__snapshots__/DocsButton.test.js.snap +1 -0
  107. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/HistoryButton.js +1 -0
  108. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/__tests__/__snapshots__/HistoryButton.test.js.snap +1 -0
  109. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +2 -2
  110. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +2 -2
  111. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +58 -0
  112. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonActions.js +57 -0
  113. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonConstants.js +3 -0
  114. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonReducer.js +36 -0
  115. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonSelectors.js +13 -0
  116. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButton.test.js +13 -0
  117. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonActions.test.js +31 -0
  118. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonFixtures.js +9 -0
  119. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonReducer.test.js +26 -0
  120. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonSelectors.test.js +36 -0
  121. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +26 -0
  122. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonActions.test.js.snap +98 -0
  123. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonReducer.test.js.snap +18 -0
  124. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonSelectors.test.js.snap +18 -0
  125. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +63 -0
  126. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js +41 -0
  127. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/modal.scss +20 -0
  128. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/index.js +22 -0
  129. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +2 -0
  130. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/__snapshots__/ToolbarButtons.test.js.snap +1 -0
  131. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/toolbarButtons.scss +6 -1
  132. data/webpack/ForemanInventoryUpload/Components/StatusChart/StatusChart.js +1 -1
  133. data/webpack/ForemanInventoryUpload/Components/StatusChart/__tests__/__snapshots__/StatusChart.test.js.snap +1 -1
  134. data/webpack/ForemanInventoryUpload/Components/TabContainer/tabContainer.scss +1 -1
  135. data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +6 -1
  136. data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.js +2 -4
  137. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +3 -1
  138. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +8 -0
  139. data/webpack/ForemanInventoryUpload/ForemanInventoryUploadReducers.js +2 -0
  140. data/webpack/ForemanRhCloudPages.js +9 -0
  141. data/webpack/ForemanRhCloudReducers.js +2 -0
  142. data/webpack/ForemanRhCloudSelectors.js +5 -0
  143. data/webpack/ForemanRhCloudTestHelpers.js +17 -3
  144. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +33 -0
  145. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsActions.js +57 -0
  146. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsConstants.js +4 -0
  147. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsReducer.js +24 -0
  148. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsSelectors.js +6 -0
  149. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettings.test.js +18 -0
  150. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsActions.test.js +62 -0
  151. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsReducer.test.js +33 -0
  152. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsSelectors.test.js +21 -0
  153. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +15 -0
  154. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsActions.test.js.snap +65 -0
  155. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsReducer.test.js.snap +19 -0
  156. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsSelectors.test.js.snap +9 -0
  157. data/webpack/InsightsCloudSync/Components/InsightsSettings/index.js +21 -0
  158. data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +16 -0
  159. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.fixtures.js +1 -0
  160. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +45 -0
  161. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/InsightsSyncSwitcher.test.js +17 -0
  162. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/__snapshots__/InsightsSyncSwitcher.test.js.snap +38 -0
  163. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/index.js +1 -0
  164. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/insightsSyncSwitcher.scss +3 -0
  165. data/webpack/InsightsCloudSync/InsightsCloudSync.js +38 -5
  166. data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +3 -0
  167. data/webpack/InsightsCloudSync/InsightsCloudSyncActions.js +10 -11
  168. data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +0 -2
  169. data/webpack/InsightsCloudSync/InsightsCloudSyncReducers.js +7 -2
  170. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +49 -9
  171. data/webpack/InsightsCloudSync/index.js +2 -1
  172. data/webpack/InsightsHostDetailsTab/InsightsTab.js +64 -0
  173. data/webpack/InsightsHostDetailsTab/InsightsTab.scss +86 -0
  174. data/webpack/InsightsHostDetailsTab/InsightsTabActions.js +31 -0
  175. data/webpack/InsightsHostDetailsTab/InsightsTabConstants.js +2 -0
  176. data/webpack/InsightsHostDetailsTab/InsightsTabReducer.js +19 -0
  177. data/webpack/InsightsHostDetailsTab/InsightsTabSelectors.js +3 -0
  178. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.fixtures.js +25 -0
  179. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js +13 -0
  180. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabActions.test.js +19 -0
  181. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabIntegration.test.js +17 -0
  182. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabReducer.test.js +26 -0
  183. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabSelectors.test.js +13 -0
  184. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTab.test.js.snap +30 -0
  185. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabActions.test.js.snap +58 -0
  186. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabReducer.test.js.snap +34 -0
  187. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabSelectors.test.js.snap +20 -0
  188. data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +69 -0
  189. data/webpack/InsightsHostDetailsTab/components/ListItem/index.js +1 -0
  190. data/webpack/InsightsHostDetailsTab/index.js +20 -0
  191. data/webpack/__mocks__/foremanReact/constants.js +5 -0
  192. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +8 -0
  193. data/webpack/__tests__/ForemanRhCloudSelectors.test.js +4 -1
  194. data/webpack/__tests__/ForemanRhCloudTestHelpers.test.js +12 -2
  195. data/webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap +10 -9
  196. data/webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap +27 -2
  197. data/webpack/index.js +2 -12
  198. data/webpack/stories/decorators/withCardsDecorator.js +1 -1
  199. metadata +120 -12
  200. data/lib/tasks/generator.rake +0 -29
  201. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/hostObfuscationSwitcher.scss +0 -0
@@ -0,0 +1,23 @@
1
+ module InsightsCloud
2
+ module Async
3
+ class InsightsScheduledSync < ::ApplicationJob
4
+ def perform
5
+ unless Setting[:allow_auto_insights_sync]
6
+ logger.debug(
7
+ 'The scheduled process is disabled due to the "allow_auto_insights_sync"
8
+ setting being set to false.'
9
+ )
10
+ return
11
+ end
12
+
13
+ InsightsFullSync.perform_later()
14
+ ensure
15
+ self.class.set(:wait => 24.hours).perform_later
16
+ end
17
+
18
+ def self.singleton_job_name
19
+ name
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,50 @@
1
+ module InventorySync
2
+ module Async
3
+ class HostResult
4
+ def initialize(result)
5
+ @total = result['total']
6
+ @count = result['count']
7
+ @page = result['page']
8
+ @per_page = result['per_page']
9
+ @fqdns = result["results"].map { |host| host['fqdn'] }
10
+ end
11
+
12
+ def status_hashes
13
+ @fqdns.map do |fqdn|
14
+ host_id = host_id(fqdn)
15
+ if host_id
16
+ touched << host_id
17
+ {
18
+ host_id: host_id,
19
+ status: InventorySync::InventoryStatus::SYNC,
20
+ reported_at: Time.current,
21
+ }
22
+ end
23
+ end.compact
24
+ end
25
+
26
+ def touched
27
+ @touched ||= []
28
+ end
29
+
30
+ def host_id(fqdn)
31
+ hosts[fqdn]
32
+ end
33
+
34
+ def hosts
35
+ @hosts ||= Hash[
36
+ Host.where(name: @fqdns).pluck(:name, :id)
37
+ ]
38
+ end
39
+
40
+ def percentage
41
+ ratio = @per_page * @page * 1.0 / @total * 100
42
+ (ratio > 100) ? 100 : ratio.truncate(2)
43
+ end
44
+
45
+ def last?
46
+ @total <= @per_page * @page
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,80 @@
1
+ require 'rest-client'
2
+
3
+ module InventorySync
4
+ module Async
5
+ class InventoryFullSync < ::ApplicationJob
6
+ include ::ForemanRhCloud::CloudAuth
7
+
8
+ def perform(organization)
9
+ @organization = organization
10
+ @subscribed_hosts_ids = Set.new(
11
+ ForemanInventoryUpload::Generators::Queries.for_slice(
12
+ Host.unscoped.where(organization: organization)
13
+ ).pluck(:id)
14
+ )
15
+ @host_statuses = {
16
+ sync: 0,
17
+ disconnect: 0,
18
+ }
19
+
20
+ InventorySync::InventoryStatus.transaction do
21
+ InventorySync::InventoryStatus.where(host_id: @subscribed_hosts_ids).delete_all
22
+ page = 1
23
+ loop do
24
+ api_response = query_inventory(page)
25
+ results = HostResult.new(api_response)
26
+ logger.debug("Downloading cloud inventory data: #{results.percentage}%")
27
+ update_hosts_status(results.status_hashes, results.touched)
28
+ @host_statuses[:sync] += results.touched.size
29
+ page += 1
30
+ break if results.last?
31
+ end
32
+ add_missing_hosts_statuses(@subscribed_hosts_ids)
33
+ @host_statuses[:disconnect] += @subscribed_hosts_ids.size
34
+ end
35
+
36
+ logger.debug("Synced hosts amount: #{@host_statuses[:sync]}")
37
+ logger.debug("Disconnected hosts amount: #{@host_statuses[:disconnect]}")
38
+
39
+ @host_statuses
40
+ end
41
+
42
+ private
43
+
44
+ def update_hosts_status(status_hashes, touched)
45
+ InventorySync::InventoryStatus.create(status_hashes)
46
+ @subscribed_hosts_ids.subtract(touched)
47
+ end
48
+
49
+ def add_missing_hosts_statuses(hosts_ids)
50
+ InventorySync::InventoryStatus.create(
51
+ hosts_ids.map do |host_id|
52
+ {
53
+ host_id: host_id,
54
+ status: InventorySync::InventoryStatus::DISCONNECT,
55
+ reported_at: Time.current,
56
+ }
57
+ end
58
+ )
59
+ end
60
+
61
+ def query_inventory(page = 1)
62
+ hosts_inventory_response = RestClient::Request.execute(
63
+ method: :get,
64
+ url: ForemanInventoryUpload.inventory_export_url,
65
+ verify_ssl: ForemanRhCloud.verify_ssl_method,
66
+ proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
67
+ headers: {
68
+ Authorization: "Bearer #{rh_credentials}",
69
+ params: {
70
+ per_page: 100,
71
+ page: page,
72
+ },
73
+ }
74
+ )
75
+
76
+ JSON.parse(hosts_inventory_response)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,15 @@
1
+ namespace :rh_cloud_insights do
2
+ desc "Synchronize Insights inventory"
3
+ task sync: :environment do
4
+ if !ENV['organization_id'].nil?
5
+ organizations = [ Organization.where(:id => ENV['organization_id']).first ]
6
+ else
7
+ organizations = Organization.all
8
+ end
9
+
10
+ organizations.each do |organization|
11
+ InventorySync::Async::InventoryFullSync.perform_now(organization)
12
+ puts "Synchronized inventory for organization '#{organization.name}'"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ require 'tempfile'
2
+
3
+ namespace :rh_cloud_inventory do
4
+ namespace :report do
5
+ desc 'Generate inventory report to be sent to Red Hat cloud'
6
+ task generate: :environment do
7
+ portal_user = ENV['portal_user']
8
+ organizations = [ENV['organization_id']]
9
+ base_folder = ENV['target'] || Dir.pwd
10
+
11
+ unless portal_user || organizations.empty?
12
+ puts "Must specify either portal_user or organization_id"
13
+ end
14
+
15
+ User.as_anonymous_admin do
16
+ if portal_user
17
+ puts "Generating report for all organizations associated with #{portal_user}"
18
+ base_folder = File.join(base_folder, portal_user)
19
+ organizations = ForemanInventoryUpload::Generators::Queries.organizations_for_user(portal_user).pluck(:id)
20
+ end
21
+
22
+ organizations.each do |organization|
23
+ target = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(organization))
24
+ archived_report_generator = ForemanInventoryUpload::Generators::ArchivedReport.new(target, Logger.new(STDOUT))
25
+ archived_report_generator.render(organization: organization)
26
+ puts "Successfully generated #{target} for organization id #{organization}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "Synchronize Insights hosts hits"
33
+ task sync: :environment do
34
+ InsightsCloud::Async::InsightsFullSync.perform_now()
35
+ puts "Synchronized Insights hosts hits data"
36
+ end
37
+ end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "0.0.1",
3
+ "version": "0.9.13",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -47,6 +47,8 @@
47
47
  "eslint": "^4.10.0",
48
48
  "eslint-import-resolver-babel-module": "^4.0.0",
49
49
  "eslint-plugin-patternfly-react": "0.2.0",
50
+ "eslint-plugin-promise": "^4.2.1",
51
+ "eslint-plugin-spellcheck": "^0.0.17",
50
52
  "identity-obj-proxy": "^3.0.0",
51
53
  "jed": "^1.1.1",
52
54
  "jest-cli": "^23.6.0",
@@ -0,0 +1,30 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class SettingsControllerTest < ActionController::TestCase
4
+ tests InsightsCloud::SettingsController
5
+
6
+ test 'should return allow_auto_insights_sync setting' do
7
+ FactoryBot.create(:setting, :name => 'allow_auto_insights_sync', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
8
+
9
+ assert_equal false, Setting[:allow_auto_insights_sync]
10
+
11
+ get :show, session: set_session_user
12
+
13
+ assert_response :success
14
+ actual = JSON.parse(response.body)
15
+ assert_equal false, actual['insightsSyncEnabled']
16
+ end
17
+
18
+ test 'should update allow_auto_insights_sync setting' do
19
+ FactoryBot.create(:setting, :name => 'allow_auto_insights_sync', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
20
+
21
+ assert_equal false, Setting[:allow_auto_insights_sync]
22
+
23
+ patch :update, params: { insightsSyncEnabled: true }, session: set_session_user
24
+
25
+ assert_response :success
26
+ actual = JSON.parse(response.body)
27
+ assert_equal true, actual['insightsSyncEnabled']
28
+ assert_equal true, Setting[:allow_auto_insights_sync]
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ FactoryBot.define do
2
+ factory :insights_facet do
3
+ # sequence(:uuid) { |n| "uuid-#{n}" }
4
+
5
+ trait :with_hits do
6
+ hits do
7
+ Array.new(1) { association(:insights_hit, host_id: host_id) }
8
+ end
9
+ end
10
+ end
11
+
12
+ factory :insights_hit do
13
+ last_seen { Date.yesterday }
14
+ sequence(:title) { |n| "hit title #{n}" }
15
+ sequence(:solution_url) { |n| "http://example.com/solutions/#{n}" }
16
+ total_risk { 1 }
17
+ likelihood { 2 }
18
+ publish_date { Time.now }
19
+ sequence(:results_url) { |n| "http://example.com/results/#{n}" }
20
+ end
21
+ end
22
+
23
+ FactoryBot.modify do
24
+ factory :host do
25
+ trait :with_insights_hits do
26
+ after(:create) do |host, _evaluator|
27
+ host.insights = FactoryBot.create(:insights_facet, :with_hits, host_id: host.id)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -51,12 +51,44 @@ class InsightsFullSyncTest < ActiveJob::TestCase
51
51
  test 'Hits data is replaced with data from cloud' do
52
52
  InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(@hits)
53
53
 
54
- InsightsCloud::Async::InsightsFullSync.perform_now(@host1.organization)
54
+ InsightsCloud::Async::InsightsFullSync.perform_now()
55
55
 
56
56
  @host1.reload
57
57
  @host2.reload
58
58
 
59
59
  assert_equal 2, @host1.insights.hits.count
60
60
  assert_equal 1, @host2.insights.hits.count
61
+ assert_equal 'accdf444-5628-451d-bf3e-cf909ad72756', @host1.insights.uuid
62
+ assert_equal 'accdf444-5628-451d-bf3e-cf909ad72757', @host2.insights.uuid
63
+ end
64
+
65
+ test 'Hits ignoring non-existent hosts' do
66
+ hits_json = <<-HITS_JSON
67
+ [
68
+ {
69
+ "hostname": "#{@host1.name}_non_existent",
70
+ "rhel_version": "7.5",
71
+ "uuid": "accdf444-5628-451d-bf3e-cf909ad72756",
72
+ "last_seen": "2019-11-22T08:41:42.447244Z",
73
+ "title": "New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled",
74
+ "solution_url": "",
75
+ "total_risk": 2,
76
+ "likelihood": 2,
77
+ "publish_date": "2018-04-16T10:03:16Z",
78
+ "results_url": "https://cloud.redhat.com/insights/overview/stability/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/accdf444-5628-451d-bf3e-cf909ad72756/"
79
+ }
80
+ ]
81
+ HITS_JSON
82
+ hits = JSON.parse(hits_json)
83
+
84
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(hits)
85
+
86
+ InsightsCloud::Async::InsightsFullSync.perform_now()
87
+
88
+ @host1.reload
89
+ @host2.reload
90
+
91
+ assert_nil @host1.insights
92
+ assert_nil @host2.insights
61
93
  end
62
94
  end
@@ -0,0 +1,91 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class InventoryFullSyncTest < ActiveJob::TestCase
4
+ setup do
5
+ @host1 = FactoryBot.create(:host, :managed, name: 'host1')
6
+
7
+ User.current = User.find_by(login: 'secret_admin')
8
+
9
+ env = FactoryBot.create(:katello_k_t_environment)
10
+ cv = env.content_views << FactoryBot.create(:katello_content_view, organization: env.organization)
11
+
12
+ # this host would pass our plugin queries, so it could be uploaded to the cloud.
13
+ @host2 = FactoryBot.create(
14
+ :host,
15
+ :with_subscription,
16
+ :with_content,
17
+ content_view: cv.first,
18
+ lifecycle_environment: env,
19
+ organization: env.organization
20
+ )
21
+
22
+ @host2.subscription_facet.pools << FactoryBot.create(:katello_pool, account_number: '1234', cp_id: 1)
23
+
24
+ ForemanInventoryUpload::Generators::Queries.instance_variable_set(:@fact_names, nil)
25
+
26
+ inventory_json = <<-INVENTORY_JSON
27
+ {
28
+ "total": 3,
29
+ "count": 3,
30
+ "page": 1,
31
+ "per_page": 50,
32
+ "results": [{"fqdn": "#{@host1.fqdn}"}]
33
+ }
34
+ INVENTORY_JSON
35
+ @inventory = JSON.parse(inventory_json)
36
+ end
37
+
38
+ def interesting_facts
39
+ [
40
+ 'dmi::system::uuid',
41
+ 'virt::uuid',
42
+ 'cpu::cpu(s)',
43
+ 'cpu::cpu_socket(s)',
44
+ 'cpu::core(s)_per_socket',
45
+ 'memory::memtotal',
46
+ 'dmi::bios::vendor',
47
+ 'dmi::bios::version',
48
+ 'dmi::bios::relase_date',
49
+ 'uname::release',
50
+ 'lscpu::flags',
51
+ 'distribution::name',
52
+ 'distribution::version',
53
+ 'distribution::id',
54
+ 'virt::is_guest',
55
+ 'dmi::system::manufacturer',
56
+ 'dmi::system::product_name',
57
+ 'dmi::chassis::asset_tag',
58
+ 'insights_client::obfuscate_hostname_enabled',
59
+ 'insights_client::hostname',
60
+ ]
61
+ end
62
+
63
+ def fact_names
64
+ @fact_names ||= Hash[
65
+ interesting_facts.map do |fact|
66
+ [fact, FactoryBot.create(:fact_name, name: fact, type: 'Katello::RhsmFactName')]
67
+ end
68
+ ]
69
+ end
70
+
71
+ test 'Host status should be SYNC for inventory hosts' do
72
+ InventorySync::Async::InventoryFullSync.any_instance.expects(:query_inventory).returns(@inventory)
73
+
74
+ InventorySync::Async::InventoryFullSync.perform_now(@host1.organization)
75
+
76
+ @host1.reload
77
+
78
+ assert_equal InventorySync::InventoryStatus::SYNC, InventorySync::InventoryStatus.where(host_id: @host1.id).first.status
79
+ end
80
+
81
+ test 'Host status should be DISCONNECT for hosts that are not returned from cloud' do
82
+ InventorySync::Async::InventoryFullSync.any_instance.expects(:query_inventory).returns(@inventory)
83
+ FactoryBot.create(:fact_value, fact_name: fact_names['virt::uuid'], value: '1234', host: @host2)
84
+
85
+ InventorySync::Async::InventoryFullSync.perform_now(@host2.organization)
86
+
87
+ @host2.reload
88
+
89
+ assert_equal InventorySync::InventoryStatus::DISCONNECT, InventorySync::InventoryStatus.where(host_id: @host2.id).first.status
90
+ end
91
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class UploadReportJobTest < ActiveJob::TestCase
4
+ include FolderIsolation
5
+
6
+ test 'returns aborted state when disconnected' do
7
+ organization = FactoryBot.create(:organization)
8
+ Organization.any_instance.stubs(:owner_details).returns(
9
+ 'upstreamConsumer' => {
10
+ 'idCert' => 'TEST_CERT',
11
+ }
12
+ )
13
+ FactoryBot.create(:setting, :name => 'content_disconnected', :value => true)
14
+
15
+ ForemanInventoryUpload::Async::UploadReportJob.perform_now('', organization.id)
16
+
17
+ label = ForemanInventoryUpload::Async::UploadReportJob.output_label(organization.id)
18
+ progress_output = ForemanInventoryUpload::Async::ProgressOutput.get(label)
19
+ assert_match(/Upload was stopped/, progress_output.full_output)
20
+ assert_match(/exit 1/, progress_output.status)
21
+ end
22
+
23
+ test 'returns aborted state when no certificate defined on organization' do
24
+ organization = FactoryBot.create(:organization)
25
+ Organization.any_instance.expects(:owner_details).returns(nil)
26
+
27
+ ForemanInventoryUpload::Async::UploadReportJob.perform_now('', organization.id)
28
+
29
+ label = ForemanInventoryUpload::Async::UploadReportJob.output_label(organization.id)
30
+ progress_output = ForemanInventoryUpload::Async::ProgressOutput.get(label)
31
+ assert_match(/Skipping organization/, progress_output.full_output)
32
+ assert_match(/exit 1/, progress_output.status)
33
+ end
34
+ end