katello 4.3.0 → 4.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

Files changed (337) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/common/vendor.js +0 -1
  3. data/app/controllers/katello/api/v2/api_controller.rb +13 -4
  4. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +3 -0
  5. data/app/controllers/katello/api/v2/content_views_controller.rb +46 -0
  6. data/app/controllers/katello/api/v2/host_packages_controller.rb +21 -1
  7. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +30 -1
  8. data/app/controllers/katello/api/v2/organizations_controller.rb +10 -6
  9. data/app/controllers/katello/api/v2/packages_controller.rb +4 -0
  10. data/app/controllers/katello/api/v2/repositories_controller.rb +17 -7
  11. data/app/controllers/katello/api/v2/repository_sets_controller.rb +7 -0
  12. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +3 -0
  13. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +32 -0
  14. data/app/controllers/katello/remote_execution_controller.rb +5 -4
  15. data/app/helpers/katello/content_source_helper.rb +43 -0
  16. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +4 -0
  17. data/app/lib/actions/katello/cdn_configuration/update.rb +5 -7
  18. data/app/lib/actions/katello/content_view/publish.rb +5 -0
  19. data/app/lib/actions/katello/content_view_version/incremental_update.rb +17 -3
  20. data/app/lib/actions/katello/repository/discover.rb +1 -14
  21. data/app/lib/actions/katello/repository/filtered_index_content.rb +1 -1
  22. data/app/lib/actions/pulp3/content_view_version/import.rb +7 -0
  23. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +7 -5
  24. data/app/lib/actions/pulp3/repository/copy_content.rb +1 -1
  25. data/app/lib/actions/pulp3/repository/save_artifact.rb +1 -0
  26. data/app/lib/katello/concerns/base_template_scope_extensions.rb +11 -0
  27. data/app/lib/katello/errors.rb +3 -3
  28. data/app/lib/katello/logging.rb +6 -1
  29. data/app/lib/katello/repo_discovery.rb +27 -19
  30. data/app/lib/katello/resources/cdn/katello_cdn.rb +41 -3
  31. data/app/lib/katello/resources/cdn.rb +4 -2
  32. data/app/lib/katello/util/deduplication_migrator.rb +105 -0
  33. data/app/models/katello/candlepin/repository_mapper.rb +1 -1
  34. data/app/models/katello/cdn_configuration.rb +38 -6
  35. data/app/models/katello/concerns/host_managed_extensions.rb +23 -1
  36. data/app/models/katello/concerns/organization_extensions.rb +5 -1
  37. data/app/models/katello/concerns/pulp_database_unit.rb +59 -173
  38. data/app/models/katello/concerns/remote_execution_proxy_selector_extensions.rb +11 -0
  39. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -1
  40. data/app/models/katello/content_view.rb +4 -4
  41. data/app/models/katello/content_view_filter.rb +1 -1
  42. data/app/models/katello/content_view_history.rb +1 -1
  43. data/app/models/katello/content_view_version.rb +6 -2
  44. data/app/models/katello/content_view_version_export_history.rb +1 -1
  45. data/app/models/katello/deb.rb +1 -3
  46. data/app/models/katello/docker_meta_tag.rb +1 -1
  47. data/app/models/katello/erratum.rb +0 -15
  48. data/app/models/katello/glue/pulp/repos.rb +1 -1
  49. data/app/models/katello/host/content_facet.rb +2 -27
  50. data/app/models/katello/host/info_provider.rb +9 -0
  51. data/app/models/katello/host/subscription_facet.rb +2 -2
  52. data/app/models/katello/hostgroup/content_facet.rb +2 -2
  53. data/app/models/katello/product.rb +1 -1
  54. data/app/models/katello/product_content.rb +2 -2
  55. data/app/models/katello/repository.rb +10 -9
  56. data/app/models/katello/root_repository.rb +24 -13
  57. data/app/models/katello/rpm.rb +8 -2
  58. data/app/models/setting/content.rb +6 -3
  59. data/app/services/cert/rhsm_client.rb +1 -5
  60. data/app/services/katello/content_unit_indexer.rb +166 -0
  61. data/app/services/katello/organization_creator.rb +12 -4
  62. data/app/services/katello/pulp/repository/docker.rb +1 -1
  63. data/app/services/katello/pulp/repository/yum.rb +0 -54
  64. data/app/services/katello/pulp/repository.rb +0 -6
  65. data/app/services/katello/pulp3/ansible_collection.rb +26 -10
  66. data/app/services/katello/pulp3/api/apt.rb +7 -0
  67. data/app/services/katello/pulp3/content_view_version/import.rb +11 -2
  68. data/app/services/katello/pulp3/deb.rb +10 -9
  69. data/app/services/katello/pulp3/docker_manifest.rb +6 -5
  70. data/app/services/katello/pulp3/docker_manifest_list.rb +23 -6
  71. data/app/services/katello/pulp3/docker_tag.rb +16 -7
  72. data/app/services/katello/pulp3/erratum.rb +51 -56
  73. data/app/services/katello/pulp3/file_unit.rb +9 -6
  74. data/app/services/katello/pulp3/generic_content_unit.rb +11 -12
  75. data/app/services/katello/pulp3/module_stream.rb +76 -30
  76. data/app/services/katello/pulp3/package_group.rb +5 -5
  77. data/app/services/katello/pulp3/pulp_content_unit.rb +19 -11
  78. data/app/services/katello/pulp3/repository/apt.rb +5 -3
  79. data/app/services/katello/pulp3/repository/docker.rb +14 -7
  80. data/app/services/katello/pulp3/repository/generic.rb +1 -1
  81. data/app/services/katello/pulp3/repository/yum.rb +10 -12
  82. data/app/services/katello/pulp3/repository.rb +26 -7
  83. data/app/services/katello/pulp3/repository_mirror.rb +18 -5
  84. data/app/services/katello/pulp3/rpm.rb +13 -13
  85. data/app/services/katello/pulp3/srpm.rb +10 -9
  86. data/app/services/katello/repository_type.rb +15 -4
  87. data/app/services/katello/repository_type_manager.rb +1 -1
  88. data/app/services/katello/ui_notifications/subscriptions/manifest_expired_warning.rb +1 -1
  89. data/app/services/katello/upstream_connection_checker.rb +2 -2
  90. data/app/views/foreman/job_templates/change_content_source.erb +1 -31
  91. data/app/views/foreman/job_templates/install_errata.erb +6 -9
  92. data/app/views/foreman/job_templates/install_errata_by_search_query.erb +26 -0
  93. data/app/views/foreman/job_templates/install_packages_by_search_query.erb +19 -0
  94. data/app/views/katello/api/v2/cdn_configurations/show.json.rabl +1 -1
  95. data/app/views/katello/api/v2/environments/show.json.rabl +9 -0
  96. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -0
  97. data/app/views/katello/layouts/react.html.erb +0 -1
  98. data/app/views/katello/sync_management/_repo.html.erb +36 -25
  99. data/config/initializers/monkeys.rb +0 -1
  100. data/config/routes/api/v2.rb +1 -0
  101. data/config/routes/overrides.rb +3 -0
  102. data/config/routes.rb +2 -0
  103. data/db/migrate/20150930183738_migrate_content_hosts.rb +1 -1
  104. data/db/migrate/20180612164926_add_content_org_id.rb +2 -2
  105. data/db/migrate/20211201154845_add_unique_indexes.rb +20 -0
  106. data/db/migrate/20211208034230_add_content_view_and_lifecycle_environment.rb +6 -0
  107. data/db/migrate/20211220185935_clean_duplicate_content_units.rb +144 -0
  108. data/db/migrate/20220110223754_update_disconnected_settings.rb +20 -0
  109. data/db/migrate/20220120163252_fix_docker_download_policy.rb +11 -0
  110. data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +22 -0
  111. data/db/migrate/20220127120843_fix_debian_download_policy.rb +11 -0
  112. data/db/migrate/20220204171908_rename_docker_tags_whitelist_and_add_exclude_tags.rb +8 -0
  113. data/db/migrate/20220207140355_change_deb_attributes_size_limit.rb +7 -0
  114. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  115. data/engines/bastion/app/views/bastion/layouts/application.html.erb +0 -1
  116. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +0 -1
  117. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/content-credentials.controller.js +1 -1
  118. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-products.controller.js +1 -1
  119. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-repositories.controller.js +1 -1
  120. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-traces-modal.html +1 -1
  121. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment.html +26 -1
  122. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +212 -152
  123. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/packages.controller.js +1 -0
  124. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +20 -8
  125. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-manage-content.controller.js +2 -3
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +8 -3
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +34 -30
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +16 -2
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +35 -15
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +5 -4
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.routes.js +4 -3
  132. data/lib/katello/engine.rb +4 -0
  133. data/lib/katello/permission_creator.rb +1 -1
  134. data/lib/katello/permissions/host_permissions.rb +3 -1
  135. data/lib/katello/plugin.rb +4 -1
  136. data/lib/katello/repository_types/deb.rb +0 -1
  137. data/lib/katello/repository_types/docker.rb +4 -4
  138. data/lib/katello/repository_types/file.rb +0 -1
  139. data/lib/katello/repository_types/ostree.rb +4 -0
  140. data/lib/katello/repository_types/python.rb +5 -1
  141. data/lib/katello/repository_types/yum.rb +2 -9
  142. data/lib/katello/tasks/content_view_import_only.rake +34 -0
  143. data/lib/katello/tasks/import_applicability.rake +1 -1
  144. data/lib/katello/tasks/jenkins.rake +0 -2
  145. data/lib/katello/tasks/repository.rake +4 -1
  146. data/lib/katello/tasks/upgrades/4.4/publish_import_cvvs.rake +17 -0
  147. data/lib/katello/version.rb +1 -1
  148. data/locale/action_names.rb +8 -7
  149. data/locale/bn/katello.po +1402 -650
  150. data/locale/cs/katello.po +1217 -96
  151. data/locale/de/katello.po +2359 -1347
  152. data/locale/en/katello.po +1216 -94
  153. data/locale/es/katello.po +2201 -1172
  154. data/locale/fr/katello.po +2601 -1615
  155. data/locale/gu/katello.po +1564 -814
  156. data/locale/hi/katello.po +1563 -810
  157. data/locale/it/katello.po +1311 -282
  158. data/locale/ja/katello.po +2534 -1518
  159. data/locale/katello.pot +3430 -1326
  160. data/locale/kn/katello.po +1564 -812
  161. data/locale/ko/katello.po +1441 -409
  162. data/locale/mr/katello.po +1564 -776
  163. data/locale/or/katello.po +1565 -813
  164. data/locale/pa/katello.po +1559 -792
  165. data/locale/pt/katello.po +1314 -277
  166. data/locale/pt_BR/katello.po +2226 -1181
  167. data/locale/ru/katello.po +1587 -563
  168. data/locale/ta/katello.po +1373 -619
  169. data/locale/te/katello.po +1564 -810
  170. data/locale/zh_CN/katello.po +2936 -1890
  171. data/locale/zh_TW/katello.po +1508 -606
  172. data/webpack/__mocks__/foremanReact/{redux/actions/toasts.js → components/ToastsList/index.js} +3 -2
  173. data/webpack/components/ActionableDetail.js +35 -21
  174. data/webpack/components/Content/Details/__tests__/ContentDetailInfo.test.js +0 -2
  175. data/webpack/components/Content/Details/__tests__/ContentDetailRepositories.test.js +0 -2
  176. data/webpack/components/Content/Details/__tests__/ContentDetails.test.js +0 -2
  177. data/webpack/components/Content/__tests__/ContentPage.test.js +0 -2
  178. data/webpack/components/Content/__tests__/ContentTable.test.js +0 -2
  179. data/webpack/components/EditableSwitch.js +8 -2
  180. data/webpack/components/EditableTextInput/EditableTextInput.js +44 -86
  181. data/webpack/components/EditableTextInput/__tests__/editableTextInput.test.js +3 -3
  182. data/webpack/components/Errata/index.js +19 -11
  183. data/webpack/components/Packages/index.js +1 -1
  184. data/webpack/components/Search/Search.js +5 -2
  185. data/webpack/components/Search/__tests__/search.test.js +2 -3
  186. data/webpack/components/SelectOrg/SetOrganization.js +1 -1
  187. data/webpack/components/Table/PageControls.js +3 -6
  188. data/webpack/components/Table/TableHooks.js +46 -7
  189. data/webpack/components/Table/TableWrapper.js +14 -3
  190. data/webpack/components/TypeAhead/TypeAhead.js +5 -1
  191. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +4 -1
  192. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +2 -1
  193. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +1 -1
  194. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +3 -4
  195. data/webpack/components/extensions/HostDetails/HostDetailsActions.js +2 -0
  196. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +18 -2
  197. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesConstants.js +12 -0
  198. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +1 -1
  199. data/webpack/components/extensions/HostDetails/Tabs/{ErrataTab.js → ErrataTab/ErrataTab.js} +30 -21
  200. data/webpack/components/extensions/HostDetails/Tabs/{ErrataTab.scss → ErrataTab/ErrataTab.scss} +0 -0
  201. data/webpack/components/extensions/HostDetails/Tabs/{ErratumExpansionContents.js → ErrataTab/ErratumExpansionContents.js} +0 -0
  202. data/webpack/components/extensions/HostDetails/Tabs/{ErratumExpansionDetail.js → ErrataTab/ErratumExpansionDetail.js} +0 -0
  203. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataActions.js +3 -3
  204. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataConstants.js +11 -0
  205. data/webpack/components/extensions/HostDetails/{HostErrata → Tabs/ErrataTab}/HostErrataSelectors.js +0 -0
  206. data/webpack/components/extensions/HostDetails/Tabs/PackageInstallModal.js +279 -0
  207. data/webpack/components/extensions/HostDetails/Tabs/PackageInstallModal.scss +3 -0
  208. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +125 -8
  209. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +27 -4
  210. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +2 -1
  211. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +6 -3
  212. data/webpack/components/extensions/HostDetails/Tabs/{EnableTracerEmptyState.js → TracesTab/EnableTracerEmptyState.js} +0 -0
  213. data/webpack/components/extensions/HostDetails/Tabs/{EnableTracerModal.js → TracesTab/EnableTracerModal.js} +3 -2
  214. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesActions.js → TracesTab/HostTracesActions.js} +2 -2
  215. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesConstants.js → TracesTab/HostTracesConstants.js} +0 -0
  216. data/webpack/components/extensions/HostDetails/Tabs/{HostTracesSelectors.js → TracesTab/HostTracesSelectors.js} +0 -0
  217. data/webpack/components/extensions/HostDetails/Tabs/{TracesTab.js → TracesTab/TracesTab.js} +8 -5
  218. data/webpack/components/extensions/HostDetails/Tabs/{TracesTab.scss → TracesTab/TracesTab.scss} +0 -0
  219. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +17 -18
  220. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +385 -0
  221. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packages.fixtures.json +1 -1
  222. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +58 -7
  223. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +2 -2
  224. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +4 -4
  225. data/webpack/components/extensions/HostDetails/Tabs/__tests__/yumInstallablePackages.fixtures.json +72 -0
  226. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +12 -5
  227. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesActions.js +18 -0
  228. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesConstants.js +3 -0
  229. data/webpack/components/extensions/HostDetails/YumInstallablePackages/YumInstallablePackagesSelectors.js +16 -0
  230. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +19 -0
  231. data/webpack/components/pf3Table/components/Table.js +2 -3
  232. data/webpack/components/pf3Table/components/Table.test.js +0 -3
  233. data/webpack/components/pf3Table/components/__snapshots__/Table.test.js.snap +9 -8
  234. data/webpack/containers/Application/config.js +5 -0
  235. data/webpack/global_index.js +1 -1
  236. data/webpack/global_test_setup.js +1 -1
  237. data/webpack/index.js +7 -0
  238. data/webpack/scenes/AnsibleCollections/Details/__tests__/AnsibleCollectionDetails.test.js +0 -2
  239. data/webpack/scenes/AnsibleCollections/__tests__/AnsibleCollectionPage.test.js +0 -2
  240. data/webpack/scenes/AnsibleCollections/__tests__/AnsibleCollectionsTable.test.js +0 -2
  241. data/webpack/scenes/Content/ContentConfig.js +55 -5
  242. data/webpack/scenes/Content/ContentPage.js +1 -1
  243. data/webpack/scenes/Content/Details/ContentDetails.js +1 -1
  244. data/webpack/scenes/Content/Details/ContentInfo.js +1 -1
  245. data/webpack/scenes/Content/Details/ContentRepositories.js +1 -1
  246. data/webpack/scenes/Content/Details/__tests__/contentDetail.test.js +4 -4
  247. data/webpack/scenes/Content/Table/ContentTable.js +1 -1
  248. data/webpack/scenes/Content/__tests__/contentTable.test.js +3 -3
  249. data/webpack/scenes/ContentViews/ContentViewsConstants.js +2 -1
  250. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +6 -6
  251. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +2 -2
  252. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +21 -27
  253. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +5 -5
  254. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +8 -3
  255. data/webpack/scenes/ContentViews/Details/DetailsContainer.js +11 -16
  256. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetails.js +2 -2
  257. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +14 -8
  258. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/__tests__/CVRpmMatchContentModal.test.js +2 -2
  259. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +2 -3
  260. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +2 -9
  261. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +3 -5
  262. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +2 -10
  263. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataIDFilter.test.js +2 -3
  264. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilter.test.js +2 -3
  265. data/webpack/scenes/ContentViews/Details/Histories/__tests__/contentViewHistory.test.js +2 -2
  266. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +1 -1
  267. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +23 -2
  268. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +11 -5
  269. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +16 -17
  270. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +1 -1
  271. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -6
  272. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +30 -34
  273. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +9 -8
  274. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +13 -15
  275. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +1 -1
  276. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +4 -4
  277. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +3 -3
  278. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +5 -3
  279. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +2 -2
  280. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +43 -0
  281. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +87 -0
  282. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +90 -0
  283. data/webpack/scenes/Hosts/ChangeContentSource/components/FormField.js +43 -0
  284. data/webpack/scenes/Hosts/ChangeContentSource/constants.js +3 -0
  285. data/webpack/scenes/Hosts/ChangeContentSource/helpers.js +27 -0
  286. data/webpack/scenes/Hosts/ChangeContentSource/index.js +126 -0
  287. data/webpack/scenes/Hosts/ChangeContentSource/selectors.js +42 -0
  288. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +11 -0
  289. data/webpack/scenes/ModuleStreams/Details/Profiles/__tests__/ModuleStreamDetailProfiles.test.js +0 -1
  290. data/webpack/scenes/ModuleStreams/Details/__tests__/ModuleStreamDetails.test.js +0 -2
  291. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +0 -2
  292. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamsTable.test.js +0 -2
  293. data/webpack/scenes/Organizations/OrganizationActions.js +5 -1
  294. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +31 -1
  295. data/webpack/scenes/RedHatRepositories/__tests__/RedHatRepositoriesPage.test.js +16 -0
  296. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +11 -2
  297. data/webpack/scenes/RedHatRepositories/helpers.js +5 -5
  298. data/webpack/scenes/RedHatRepositories/index.js +11 -3
  299. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/AirGappedTypeForm.js +81 -0
  300. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnConfigurationConstants.js +13 -0
  301. data/webpack/scenes/Subscriptions/Manifest/{CdnConfigurationForm.scss → CdnConfigurationTab/CdnConfigurationForm.scss} +0 -0
  302. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +106 -0
  303. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/UpstreamServerTypeForm.js +259 -0
  304. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/AirGappedTypeForm.test.js +44 -0
  305. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/CdnTypeForm.test.js +67 -0
  306. data/webpack/scenes/Subscriptions/Manifest/{__tests__/CdnConfigurationForm.test.js → CdnConfigurationTab/__tests__/UpstreamServerTypeForm.test.js} +46 -17
  307. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/index.js +97 -0
  308. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +6 -1
  309. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +0 -1
  310. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +0 -1
  311. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +3 -2
  312. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +4 -0
  313. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +9 -0
  314. data/webpack/scenes/Tasks/TaskActions.js +1 -1
  315. data/webpack/scenes/Tasks/__tests__/__snapshots__/TaskActions.test.js.snap +3 -2
  316. data/webpack/services/api/testHelpers.js +5 -3
  317. data/webpack/utils/helpers.js +6 -3
  318. metadata +81 -58
  319. data/app/services/katello/pulp/deb.rb +0 -55
  320. data/app/services/katello/pulp/distribution.rb +0 -7
  321. data/app/services/katello/pulp/docker_blob.rb +0 -7
  322. data/app/services/katello/pulp/docker_manifest.rb +0 -13
  323. data/app/services/katello/pulp/docker_manifest_list.rb +0 -14
  324. data/app/services/katello/pulp/docker_tag.rb +0 -14
  325. data/app/services/katello/pulp/erratum.rb +0 -129
  326. data/app/services/katello/pulp/file_unit.rb +0 -21
  327. data/app/services/katello/pulp/module_stream.rb +0 -39
  328. data/app/services/katello/pulp/package_category.rb +0 -7
  329. data/app/services/katello/pulp/package_group.rb +0 -20
  330. data/app/services/katello/pulp/pulp_content_unit.rb +0 -156
  331. data/app/services/katello/pulp/rpm.rb +0 -57
  332. data/app/services/katello/pulp/srpm.rb +0 -29
  333. data/app/services/katello/pulp/yum_metadata_file.rb +0 -30
  334. data/lib/monkeys/pulp3_13_checksumfix.rb +0 -17
  335. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationHooks.js +0 -2
  336. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
  337. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationForm.js +0 -185
@@ -15,17 +15,19 @@ module Actions
15
15
  metadata: metadata
16
16
  ).output
17
17
 
18
- import_output = plan_action(
18
+ plan_action(
19
19
  ::Actions::Pulp3::ContentViewVersion::Import,
20
20
  content_view_version_id: content_view_version.id,
21
21
  smart_proxy_id: smart_proxy.id,
22
22
  importer_data: importer_output[:importer_data],
23
23
  path: path,
24
24
  metadata: metadata
25
- ).output
26
-
27
- plan_action(Actions::Pulp3::Repository::SaveVersions, content_view_version.importable_repositories.pluck(:id),
28
- tasks: import_output[:pulp_tasks])
25
+ )
26
+ concurrence do
27
+ content_view_version.importable_repositories.each do |repo|
28
+ plan_action(Actions::Pulp3::Repository::SaveVersion, repo)
29
+ end
30
+ end
29
31
  plan_action(
30
32
  ::Actions::Pulp3::ContentViewVersion::CreateImportHistory,
31
33
  content_view_version_id: content_view_version.id,
@@ -13,7 +13,7 @@ module Actions
13
13
  target = ::Katello::Repository.find(input[:target_repository_id] || input[:target_repository])
14
14
  service = target.backend_service(smart_proxy)
15
15
  output[:pulp_tasks] = if input[:copy_all]
16
- service.copy_all(source, mirror: input[:mirror] || false)
16
+ service.copy_all(source, input)
17
17
  else
18
18
  service.copy_content_for_source(source, input)
19
19
  end
@@ -27,6 +27,7 @@ module Actions
27
27
  []
28
28
  else
29
29
  output[:pulp_tasks] = [content_backend_service.content_api_create(relative_path: input[:options][:file_name],
30
+ repository_id: repository.id,
30
31
  artifact: artifact_href,
31
32
  content_type: content_type)]
32
33
  end
@@ -288,6 +288,17 @@ module Katello
288
288
  Katello.with_katello_agent?
289
289
  end
290
290
 
291
+ include Katello::ContentSourceHelper
292
+
293
+ apipie :method, "Generate script to change a host's content source" do
294
+ returns String
295
+ end
296
+ def change_content_source(host, ca_cert)
297
+ return missing_content_source(host) unless host.content_source
298
+
299
+ prepare_ssl_cert(ca_cert) + configure_subman(host.content_source)
300
+ end
301
+
291
302
  private
292
303
 
293
304
  def host_subscription_facet(host)
@@ -145,10 +145,10 @@ module Katello
145
145
  end
146
146
  end
147
147
 
148
- class DisconnectedMode < StandardError
148
+ class SubscriptionConnectionNotEnabled < StandardError
149
149
  def message
150
- _("You are currently operating in disconnected mode where access to Red Hat Subcription Management " \
151
- "is prohibited. If you would like to change this, please update the content setting 'Disconnected mode'.")
150
+ _("Access to Red Hat Subscription Management " \
151
+ "is prohibited. If you would like to change this, please update the content setting 'Subscription connection enabled'.")
152
152
  end
153
153
  end
154
154
 
@@ -19,9 +19,9 @@ module Katello
19
19
  class Timer
20
20
  def initialize(key = "default")
21
21
  @key = key
22
- @start_time = Time.now
23
22
  Thread.current[:timers] ||= {}
24
23
  Thread.current[:timers][key] = self
24
+ self.start
25
25
  end
26
26
 
27
27
  def start
@@ -38,6 +38,11 @@ module Katello
38
38
  Rails.logger.info "Timer #{@key} stopping at #{Time.now}: #{duration} sec"
39
39
  end
40
40
 
41
+ def log(msg = nil)
42
+ duration = (Time.now - @start_time).truncate(2)
43
+ Rails.logger.info ["Timer #{@key} running at #{Time.now}", msg, "#{duration} sec"].compact.join(': ')
44
+ end
45
+
41
46
  def self.find_by_key(key)
42
47
  if Thread.current&.[](:timers)&.[](key)
43
48
  Thread.current[:timers][key]
@@ -1,10 +1,12 @@
1
1
  module Katello
2
2
  class RepoDiscovery
3
+ include Katello::Util::HttpProxy
4
+
3
5
  attr_reader :found, :crawled, :to_follow
4
6
 
5
7
  # rubocop:disable Metrics/ParameterLists
6
8
  def initialize(url, content_type = 'yum', upstream_username = nil,
7
- upstream_password = nil, search = '*', proxy = {}, crawled = [],
9
+ upstream_password = nil, search = '*', crawled = [],
8
10
  found = [], to_follow = [])
9
11
  @uri = uri(url)
10
12
  @content_type = content_type
@@ -14,7 +16,6 @@ module Katello
14
16
  @found = found
15
17
  @crawled = crawled
16
18
  @to_follow = to_follow
17
- @proxy = proxy
18
19
  end
19
20
  # rubocop:enable Metrics/ParameterLists
20
21
 
@@ -42,42 +43,49 @@ module Katello
42
43
  private
43
44
 
44
45
  def docker_search
45
- params = {
46
- :accept => :json
46
+ request_params = {
47
+ method: :get,
48
+ headers: { accept: :json },
49
+ url: "#{@uri}v1/search?q=#{@search}"
47
50
  }
48
- params[:user] = @upstream_username unless @upstream_username.empty?
49
- params[:password] = @upstream_password unless @upstream_password.empty?
50
-
51
- RestClient.proxy = nil
52
51
 
53
- if @proxy && @proxy[:proxy_host]
54
- proxy_uri = URI(@proxy[:proxy_host])
55
- proxy_uri.user = @proxy[:proxy_user] if @proxy[:proxy_user]
56
- proxy_uri.password = @proxy[:proxy_password] if @proxy[:proxy_password]
57
- proxy_uri.port = @proxy[:proxy_port] if @proxy[:proxy_port]
58
-
59
- RestClient.proxy = proxy_uri.to_s
60
- end
52
+ request_params[:headers][:user] = @upstream_username unless @upstream_username.empty?
53
+ request_params[:headers][:password] = @upstream_password unless @upstream_password.empty?
54
+ request_params[:proxy] = proxy_uri if proxy
61
55
 
62
56
  begin
63
- results = RestClient.get(@uri.to_s + "v1/search?q=#{@search}", params)
57
+ results = RestClient::Request.execute(request_params)
64
58
  JSON.parse(results)['results'].each do |result|
65
59
  @found << result['name']
66
60
  end
67
61
  rescue
68
62
  # Note: v2 endpoint does not support search
69
- results = RestClient.get(@uri.to_s + "v2/_catalog", params)
63
+ request_params[:url] = "#{@uri}v2/_catalog"
64
+ results = RestClient::Request.execute(request_params)
70
65
  @found = JSON.parse(results)['repositories']
71
66
  end
72
67
  @found.sort!
73
68
  end
74
69
 
70
+ def anemone_proxy_details
71
+ details = {}
72
+
73
+ if proxy
74
+ details[:proxy_host] = proxy_host
75
+ details[:proxy_port] = proxy_port
76
+ details[:proxy_user] = proxy.username
77
+ details[:proxy_password] = proxy.password
78
+ end
79
+
80
+ details
81
+ end
82
+
75
83
  def http_crawl(resume_point)
76
84
  resume_point_uri = URI(resume_point)
77
85
  resume_point_uri.user = @upstream_username if @upstream_username
78
86
  resume_point_uri.password = @upstream_password if @upstream_password
79
87
 
80
- Anemone.crawl(resume_point_uri, @proxy) do |anemone|
88
+ Anemone.crawl(resume_point_uri, anemone_proxy_details) do |anemone|
81
89
  anemone.focus_crawl do |page|
82
90
  @crawled << page.url.path
83
91
 
@@ -4,6 +4,8 @@ module Katello
4
4
  class KatelloCdn < CdnResource
5
5
  def initialize(url, options)
6
6
  @organization_label = options.delete(:organization_label)
7
+ @content_view_label = options.delete(:content_view_label)
8
+ @lifecycle_environment_label = options.delete(:lifecycle_environment_label)
7
9
  fail ArgumentError, "No upstream organization was specified" if @organization_label.nil?
8
10
 
9
11
  super
@@ -38,14 +40,50 @@ module Katello
38
40
  get("/katello/api/v2/organizations/#{organization['id']}/download_debug_certificate")
39
41
  end
40
42
 
43
+ def content_view_id
44
+ rs = get("/katello/api/v2/organizations/#{organization['id']}/content_views?name=#{CGI.escape(@content_view_label)}")
45
+ content_view = JSON.parse(rs)['results']&.first
46
+ if content_view.blank?
47
+ fail _("Upstream organization %{org_label} does not have a content view with the label %{cv_label}") % { org_label: @organization_label,
48
+ cv_label: @content_view_label }
49
+ end
50
+ content_view["id"]
51
+ end
52
+
53
+ def lifecycle_environment_id
54
+ rs = get("/katello/api/v2/organizations/#{organization['id']}/environments")
55
+ env = JSON.parse(rs)['results'].find { |lce| lce['label'] == @lifecycle_environment_label }
56
+
57
+ if env.blank?
58
+ fail _("Upstream organization %{org_label} does not have a lifecycle environment with the label %{lce_label}") % { org_label: @organization_label,
59
+ lce_label: @lifecycle_environment_label }
60
+ end
61
+ env["id"]
62
+ end
63
+
41
64
  def repository_url(content_label:)
42
- response = get("/katello/api/v2/organizations/#{organization['id']}/repositories?search=#{CGI.escape("content_label = #{content_label}")}")
65
+ params = {
66
+ search: CGI.escape("content_label = #{content_label}")
67
+ }
68
+
69
+ params[:content_view_id] = content_view_id if @content_view_label
70
+ params[:environment_id] = lifecycle_environment_id if @lifecycle_environment_label
71
+
72
+ query_params = params.map { |key, value| "#{key}=#{value}" }
73
+ url = "/katello/api/v2/organizations/#{organization['id']}/repositories?#{query_params.join('&')}"
74
+ response = get(url)
43
75
  repository = JSON.parse(response)['results'].first
44
76
 
45
77
  if repository.nil?
46
- fail _("Repository with content label %{content_label} was not found in upstream organization %{org_label}") % { content_label: content_label, org_label: @organization_label }
47
- end
78
+ msg_params = { content_label: content_label,
79
+ org_label: @organization_label,
80
+ cv_label: @content_view_label || Katello::OrganizationCreator::DEFAULT_CONTENT_VIEW_LABEL,
81
+ env_label: @lifecycle_environment_label || Katello::OrganizationCreator::DEFAULT_LIFECYCLE_ENV_LABEL
82
+ }
48
83
 
84
+ fail _("Repository with content label %{content_label} was not found in upstream organization %{org_label},"\
85
+ " content view %{cv_label} and lifecycle environment %{env_label} ") % msg_params
86
+ end
49
87
  repository['full_path']
50
88
  end
51
89
 
@@ -58,7 +58,7 @@ module Katello
58
58
 
59
59
  def self.create(product: nil, cdn_configuration:)
60
60
  options = {}
61
- if cdn_configuration.redhat?
61
+ if cdn_configuration.redhat_cdn?
62
62
  options[:ssl_client_cert] = OpenSSL::X509::Certificate.new(product.certificate)
63
63
  options[:ssl_client_key] = OpenSSL::PKey::RSA.new(product.key)
64
64
  options[:ssl_ca_file] = self.ca_file
@@ -67,6 +67,8 @@ module Katello
67
67
  options[:username] = cdn_configuration.username
68
68
  options[:password] = cdn_configuration.password
69
69
  options[:organization_label] = cdn_configuration.upstream_organization_label
70
+ options[:content_view_label] = cdn_configuration.upstream_content_view_label
71
+ options[:lifecycle_environment_label] = cdn_configuration.upstream_lifecycle_environment_label
70
72
  options[:ssl_ca_cert] = cdn_configuration.ssl_ca
71
73
  CDN::KatelloCdn.new(cdn_configuration.url, options)
72
74
  end
@@ -184,7 +186,7 @@ module Katello
184
186
  def net_http_class
185
187
  if proxy
186
188
  uri = URI(proxy.url) #Net::HTTP::Proxy ignores port as part of the url
187
- Net::HTTP::Proxy("#{uri.host}#{uri.path}", uri.port, proxy.username, proxy.password)
189
+ Net::HTTP::Proxy("#{uri.host}", uri.port, proxy.username, proxy.password)
188
190
  else
189
191
  Net::HTTP
190
192
  end
@@ -0,0 +1,105 @@
1
+ module Katello
2
+ module Util
3
+ class DeduplicationMigrator # used in db/migrate/20211201154845_add_unique_indexes.rb
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ def models_to_clean
7
+ [
8
+ {
9
+ :model => ::Katello::CapsuleLifecycleEnvironment,
10
+ :fields => [:lifecycle_environment_id, :capsule_id]
11
+ },
12
+ {
13
+ :model => ::Katello::ContentViewErratumFilterRule,
14
+ :fields => [:errata_id, :content_view_filter_id]
15
+ },
16
+ {
17
+ :model => ::Katello::ContentViewModuleStreamFilterRule,
18
+ :fields => [:module_stream_id, :content_view_filter_id]
19
+ },
20
+ {
21
+ :model => ::Katello::ContentViewPackageGroupFilterRule,
22
+ :fields => [:uuid, :content_view_filter_id]
23
+ },
24
+ {
25
+ :model =>
26
+ ::Katello::ContentViewRepository,
27
+ :fields => [:content_view_id, :repository_id]
28
+ }
29
+ ]
30
+ end
31
+
32
+ def models_to_rename
33
+ [
34
+ {
35
+ :model => ::Katello::ContentView,
36
+ :fields => [:name, :organization_id]
37
+ }
38
+ ]
39
+ end
40
+
41
+ # example ---- (IDs 1/7 and 6/8 are duplicates ) ::Katello::CapsuleLifecycleEnvironment.all
42
+ # => [#<Katello::CapsuleLifecycleEnvironment:0x0000000017e11060 id: 1, capsule_id: 1, lifecycle_environment_id: 1>,
43
+ # #<Katello::CapsuleLifecycleEnvironment:0x0000000017e10f98 id: 2, capsule_id: 1, lifecycle_environment_id: 2>,
44
+ # #<Katello::CapsuleLifecycleEnvironment:0x0000000017e10ed0 id: 3, capsule_id: 1, lifecycle_environment_id: 3>,
45
+ # ...
46
+ # #<Katello::CapsuleLifecycleEnvironment:0x0000000017e10c78 id: 6, capsule_id: 1, lifecycle_environment_id: 6>,
47
+ # #<Katello::CapsuleLifecycleEnvironment:0x0000000017e10bb0 id: 7, capsule_id: 1, lifecycle_environment_id: 1>,
48
+ # #<Katello::CapsuleLifecycleEnvironment:0x0000000017e10ac0 id: 8, capsule_id: 1, lifecycle_environment_id: 6>]
49
+ def execute!
50
+ models_to_clean.each do |model_to_clean|
51
+ rows_deleted = 0
52
+ model = model_to_clean[:model]
53
+ cleaning_queries(model_to_clean).each { |query| rows_deleted += clean_duplicates(query, model) }
54
+ if rows_deleted > 0
55
+ Rails.logger.info("Deleted #{pluralize(rows_deleted, 'duplicate table row')} from #{model.table_name}")
56
+ end
57
+ end
58
+ Rails.logger.info("Finished cleaning duplicate table rows")
59
+
60
+ models_to_rename.each do |model_to_rename|
61
+ rows_renamed = 0
62
+ model = model_to_rename[:model]
63
+ cleaning_queries(model_to_rename).each { |query| rows_renamed += rename_duplicates(query, model) }
64
+ if rows_renamed > 0
65
+ Rails.logger.info("Renamed #{pluralize(rows_renamed, 'duplicate table row')} from #{model.table_name}")
66
+ end
67
+ end
68
+ Rails.logger.info("Finished renaming duplicate table rows")
69
+ end
70
+
71
+ def cleaning_queries(model_to_clean)
72
+ model = model_to_clean[:model]
73
+ fields = model_to_clean[:fields]
74
+ dup_query = model.group(fields).having("count(*) > 1")
75
+ duplicate_entries = dup_query.count.try(:keys) # [[1, 1], [6, 1]] - the set of duplicate combinations
76
+ return [] if duplicate_entries.blank?
77
+ min_ids = dup_query.pluck('min(id)') # [1, 6] - the ids of the duplicate entries with the lowest id, in the same order as duplicate_entries
78
+ duplicate_entries.map.with_index do |entry, idx|
79
+ # [{:lifecycle_environment_id=>1, :capsule_id=>1, :min_id=>1},
80
+ # {:lifecycle_environment_id=>6, :capsule_id=>1, :min_id=>6}]
81
+ Hash[fields.zip(entry)].merge({ min_id: min_ids[idx] })
82
+ end
83
+ end
84
+
85
+ def clean_duplicates(query, model)
86
+ min_id = query.delete(:min_id)
87
+ model.where(query).where.not(id: min_id).delete_all # returns quantity deleted
88
+ end
89
+
90
+ def rename_duplicates(query, model)
91
+ min_id = query.delete(:min_id)
92
+ counter = 0
93
+ model.where(query).where.not(id: min_id).each do |duplicate|
94
+ counter += 1
95
+ old_name = duplicate.name
96
+ new_name = "#{duplicate.name}_#{duplicate.id}"
97
+ duplicate.name = new_name
98
+ duplicate.save(validate: false) # skip validation since migrations should never fail
99
+ Rails.logger.info("Content view #{old_name} (id #{duplicate.id}) renamed to #{new_name}")
100
+ end
101
+ counter
102
+ end
103
+ end
104
+ end
105
+ end
@@ -44,7 +44,7 @@ module Katello
44
44
  end
45
45
 
46
46
  def validate!
47
- return if katello_content_type == Repository::OSTREE_TYPE || Setting[:content_disconnected]
47
+ return if katello_content_type == Repository::OSTREE_TYPE || product.organization.cdn_configuration.airgapped?
48
48
  substitutor.validate_substitutions(content, substitutions)
49
49
  end
50
50
 
@@ -1,31 +1,63 @@
1
1
  module Katello
2
2
  class CdnConfiguration < Katello::Model
3
3
  include Encryptable
4
+ self.inheritance_column = nil
5
+ CDN_TYPE = 'redhat_cdn'.freeze
6
+ UPSTREAM_SERVER_TYPE = 'upstream_server'.freeze
7
+ AIRGAPPED_TYPE = 'airgapped'.freeze
8
+
9
+ TYPES = [CDN_TYPE, UPSTREAM_SERVER_TYPE, AIRGAPPED_TYPE].freeze
4
10
 
5
11
  belongs_to :organization, :inverse_of => :cdn_configuration
6
12
 
7
13
  belongs_to :ssl_ca_credential, :class_name => "Katello::ContentCredential", :inverse_of => :ssl_ca_cdn_configurations
8
14
 
9
15
  encrypts :password
16
+ validates :password, presence: true, if: :upstream_server?
17
+ validates :username, presence: true, if: :upstream_server?
18
+ validates :upstream_organization_label, presence: true, if: :upstream_server?
10
19
 
11
- validates :url, presence: true
12
- validates_with Validators::KatelloUrlFormatValidator, attributes: :url
20
+ validates :url, presence: true, unless: :airgapped?
21
+ validates_with Validators::KatelloUrlFormatValidator, attributes: :url, unless: :airgapped?
13
22
  validates_with Validators::KatelloLabelFormatValidator, attributes: :upstream_organization_label, if: proc { upstream_organization_label.present? }
14
- validate :non_redhat_configuration, unless: :redhat?
23
+ validate :non_redhat_configuration, if: :upstream_server?
24
+
25
+ before_validation :reset_fields
15
26
 
16
27
  def ssl_ca
17
28
  ssl_ca_credential&.content
18
29
  end
19
30
 
20
- def redhat?
21
- username.blank? && password.blank? && upstream_organization_label.blank? && ssl_ca_credential_id.blank?
31
+ def redhat_cdn?
32
+ type == CDN_TYPE
33
+ end
34
+
35
+ def airgapped?
36
+ type == AIRGAPPED_TYPE
37
+ end
38
+
39
+ def upstream_server?
40
+ type == UPSTREAM_SERVER_TYPE
22
41
  end
23
42
 
24
43
  private
25
44
 
45
+ def reset_fields
46
+ return if upstream_server?
47
+
48
+ self.url = nil if airgapped?
49
+ self.url ||= SETTINGS[:katello][:redhat_repository_url] if redhat_cdn?
50
+ self.username = nil
51
+ self.password = nil
52
+ self.upstream_organization_label = nil
53
+ self.ssl_ca_credential_id = nil
54
+ self.upstream_content_view_label = nil
55
+ self.upstream_lifecycle_environment_label = nil
56
+ end
57
+
26
58
  def non_redhat_configuration
27
59
  if username.blank? || password.blank? || upstream_organization_label.blank? || ssl_ca_credential_id.blank?
28
- errors.add(:base, _("Username, Password, Upstream Organization Label, and SSL CA Credential are required when using a non-Red Hat CDN."))
60
+ errors.add(:base, _("Username, Password, Upstream Organization Label, and SSL CA Credential are required when using an upstream Foreman server."))
29
61
  end
30
62
  end
31
63
  end
@@ -28,9 +28,21 @@ module Katello
28
28
  content_facet.kickstart_repository_id = valid_repos.first
29
29
  end
30
30
  end
31
+
32
+ def remote_execution_proxies(provider, *_rest)
33
+ proxies = super
34
+ if (name = subscription_facet&.registered_through)
35
+ registered_through = SmartProxy.with_features(provider)
36
+ .authorized
37
+ .where(name: name)
38
+ end
39
+ proxies[:registered_through] = registered_through || []
40
+ proxies
41
+ end
31
42
  end
32
43
 
33
44
  included do
45
+ prepend ::ForemanRemoteExecution::HostExtensions if ::Katello.with_remote_execution?
34
46
  prepend Overrides
35
47
 
36
48
  delegate :content_source_id, :content_view_id, :lifecycle_environment_id, :kickstart_repository_id, to: :content_facet, allow_nil: true
@@ -388,6 +400,16 @@ module Katello
388
400
  ::Katello::HostTracer.helpers_for(traces)
389
401
  end
390
402
 
403
+ def package_names_for_job_template(action:, search:)
404
+ actions = ['install']
405
+ case action
406
+ when 'install'
407
+ ::Katello::Rpm.yum_installable_for_host(self).search_for(search).distinct.pluck(:name)
408
+ else
409
+ fail ::Foreman::Exception.new(N_("package_names_for_job_template: Action must be one of %s"), actions.join(', '))
410
+ end
411
+ end
412
+
391
413
  def advisory_ids(search:)
392
414
  ::Katello::Erratum.installable_for_hosts([self]).search_for(search).pluck(:errata_id)
393
415
  end
@@ -414,7 +436,7 @@ end
414
436
  class ::Host::Managed::Jail < Safemode::Jail
415
437
  allow :content_source, :subscription_manager_configuration_url, :rhsm_organization_label,
416
438
  :host_collections, :pools, :hypervisor_host, :lifecycle_environment, :content_view,
417
- :installed_packages, :traces_helpers, :advisory_ids
439
+ :installed_packages, :traces_helpers, :advisory_ids, :package_names_for_job_template
418
440
  end
419
441
 
420
442
  class ActiveRecord::Associations::CollectionProxy::Jail < Safemode::Jail
@@ -55,6 +55,10 @@ module Katello
55
55
  # so that it will execute after :dependent => :destroy
56
56
  before_destroy :destroy_taxable_taxonomies
57
57
 
58
+ def self.non_audited_columns
59
+ super | [:created_in_katello]
60
+ end
61
+
58
62
  def default_content_view
59
63
  ContentView.default.where(:organization_id => self.id).first
60
64
  end
@@ -193,7 +197,7 @@ module Katello
193
197
 
194
198
  def latest_repo_discovery
195
199
  ForemanTasks::Task::DynflowTask.for_action(::Actions::Katello::Repository::Discover)
196
- .for_resource(::User.current).order("started_at").last
200
+ .where(user: ::User.current).order("started_at").last
197
201
  end
198
202
 
199
203
  def cancel_repo_discovery